Suggtestions for sending e-mail notifications from a 2 tier application with client potentially not connected to the internet - delphi

I have to add e-mail notifications to a client server application.
Notifications happen as the user do some particular action on the client UI.
If I had a middle tier or a service running at server I can imagine how to do it:
1) I simply create a DB tables with "pending notifications"
2) as a user does an action that generates a notification I add a record to the table
3) serverside I would continuously try to send those mails and removing them from the table once sending is succesful
Now I cannot do this now, I have a plan to add a service later on, but for now I must go the quick and dirty way.
So somehow what I was thinking to is to implement something like this:
1) as a notify-worth event occurs at client, the same client (my exe) tries to send the notification, upon failure it will log the notification in the "pending notifications" table (failure can be becuase lack of internet connection or any other problem)
2) I add a Timer that will work from any client machine to check for pending notifications. If there are any the client will try to send the e-mail (using a transaction: I will mark a field as "TryngToSendFromClientX" and in case of failure I will reset that field to NULL)
I think this approach would work, it has obvious limitations (if after failure no one logs into the system, no notification will be sent - same would be if service goes "down"). But can you comment on this approach and suggest a better one?
Additional notes (to better understand the scenario):
a) Note: all notifications are sent from the same e-mail account.
b) I don't need to keep track of who sent the e-mail.
c) the problem of creating the service now is that it will basically complicate significantly deployment and I need to create tools for monitoring the status of the service. Something that I will do in future but not now, in future I have plan to add more functionality (not only sending notifications) to the service, so in that case it makes more sense to create it.
d) I will send e-mails by using Indy components and SMTP server.

If you are not willing to create the service now, I think you are stuck with the scenario you describe. There are some things though you could do to circumvent the problem of no user firing up the client anymore while there are still pending messages.
You could add a commandline utility (or commandline parameter as bepe4711 suggested) that will only check for pending messages and try to send them.
Add this commandline utility to the StartUp folder or Run key in the registry. This way messages will at least get sent when the computer restarts, even if the user does not fire up the your app.
Add a scheduled task to run this utility at least once every day. The scheduled task can be added by code or by your installer.
If you do both, you will only have to worry about pending messages of users that never start their computer again.

Perhaps you can add a parameter to your client which causes it to just look at the pending notifications and send them. After this it can terminate itself. It will just act like some kind of service.
Then you install the client on the server and start it every x minutes.

I do something very similar to the approach you describe. Instead of sending emails I need to call a web service. My application is installed on several laptops and they are commonly not connected to any network.
When my application raises an exception I collect various bits of information including user comments and screen shots. Then I attempt to send this to our web service. If by chance the web service is not available. (i.e. not connected to the internet or web service is down) I write the results to an XML file on disk in the User Profile (App_Data) directory.
The one major difference is I don't poll to check to see if the server is up. I attempt to send them again on the startup of the application.

If both Systems are running on Windows, have a look at MS Message Queue. It is designed to send notifications to systems, which are not allways online. I did it in .Net, there are already easy to use classes implemented. Not sure about Delphi.

Latest version of Windows uses much more the Windows Task Scheduler, and now task can be fired on event (i.e. when a network card gets connected...). You could write a separate utility that tries to send pending notification, even if noone is logged in.

Related

Microservices out of sync

Application architecture has three microservices; let's call them A, B, and C.
A is the authority for holding user permissions (including permissions for sending SMS) and when permissions update it publishes an Event for services interested in this data.
B and C listen for permissions changes, to control sending SMS.
Main Rails App is integrating with A, B, C.
App updated A with permissions to prevent student A from receiving any SMS,
and then A published the event which gets delayed in Queueworker;
App started to send SMS through B, which is not updated yet because of Queueworker delay.
How can we ensure (or what is need to be changed in design to ensure) users will not receive SMS once permissions changed to false?
You're running into the biggest challenge of distributed systems -- the CAP theorem. To summarize, a distributed system (like you have) can never guarantee all three of the below:
Consistency - all services see the same data at the same time
Availability - all services' requests to each other receive a success or failure response
Partition tolerance - the system continues to function even when services cannot reach each other
In your specific problem, the lack of consistency is hurting you. You can fix it, but you'll have to give up one of the other points. For example, before sending each SMS, you could have service B perform a synchronous HTTP request to service A to verify that the intended recipient still has permissions to receive SMSes. This will fix your consistency issue, but creates a dependency that A must be up and running for B to function (meaning, you've lost the P from CAP).
You could also mitigate the issue by sending SMS requests as events through the same queue that the permission updates go through. It's still possible for an SMS to send after the permission was disabled, but that would only happen if the permission update came in after the SMS was meant to be sent. This is still lacking consistency, but the impact is less severe (at a cost of SMS latency).

AFNetworking and Push Notifications

I am working on an application which GET and POST information to a server. I am doing so using AFNetworking framework. My aim is to push a notification to a client whenever someone posts new info to the server. Eg: a new grade is published, the student who's grade was published must receive a notification on his iDevice.
Although I am not familiar with how Apple Push Notification works, from what I read I concluded that I need to add server side code in order to trigger a notification.
Note that I don't have access to the server. Service is provided by Fedena.
Any suggestions or hints from where to start?
APNS needs a server in order to work. The usual flow goes like this:
The iOS Application asks user to enable push notifications
Upon access granted, a device token is generated and then must be sent to the server.
Your server must be setup with the proper APNS certificates generated from the Apple Developer site
Then in your server's, when a new post is created, you need to add some logic where you load all the APNS token you've received already and then send the notification to the devices.
This is a very simple flow description but I guess you understood that you need to have access to the server to be able to do what you are trying to achieve.
Some third parties exists to handle push notifications (like Urban Airship), but those push notifications are usually pushed manually from a person, and not triggered from a server event
I recommend that you can use secondary server of your own as intermediate and use it as infrastructure back bone.You can use SignalR library. Use secondary server as to create connection between two devises. One client will push events and another client will listen to events.
Here is the link to the signalR library code written in IOS.
I am currently using these library. What you can do is start hub and connection using these library.
This library allows invoking method on server. Something like this.
[_hub invoke:#"MehtodName" withArgs:params];
What i would do is to create event registry on server. So one client can listen to event on server and other can push events or vice versa.
So your student device can invoke method "subscribe to events" and server will add it into the registry list. You can create secondary service "Publish Events". Grade publisher can publish via calling this method. Here publish events will look up registry and find interested clients and call desired method on client.
Read more about signalr through this site.
Benefit of using Signalr Over APNS.
Cost Effective. As this will save you money which you might have to pay to Apple for pushing notification.
Can Easily make it cross plateform in future. Just have to impletement similar library in Android/Windows.
Quicker as the data does not travel to apple server from your server.
Worst case you can fallback to apns any day, just put push notification code in any of your secondary server methods.
I have done battery and performance testing as well and works perfectly fine.
If you wanna know, here how it handles connection which is very reliable.
SRAutoTransport chooses the best supported transport for both client
and server. This achieved by falling back to less performant
transports. The default transport fallback is:
SRWebSocketTransport
SRServerSentEventsTransport
SRLongPollingTransport
Let me know if you have anyother question. i am currently doing similar work, might be able to help you with your issue.

iOS - Push notifications and background threading

I have a service that allows user to enter the type of events they like, and whenever a new event that fits those criteria is available in my database, I want them to get a notification.
I have been looking around at the best way to handle it and I have found two possible solutions, but I'm not very clear with which one I should use and how.
First, a solution that looked great was the didReceiveRemoteNotification method and the usage of remote silent notifications to tell the app that new content was available. But my questions remains: how can I send this remote notification to the user if I don't know which criteria he has. I mean, how can I send this notification using PHP? I'm a bit lost here.
So I found another possible solution that does look a lot like a hack (iPhone - Backgrounding to poll for events), to be able to make your app execute a method every XX minutes while it is in background. This would be way more battery consuming and I'm not even sure it would be accepted by Apple, but at least it is clear as to how it works: the app downloads data from a link with the parameters that fit the special criteria, and if there is new data, it sends a notification.
How could I combine both these methods?
EDIT
I think the main issue on my side is that I don't understand how I could check a certain PHP file whenever new data is added into mysql and make sure that it fits the criteria of the user and then send the notification. That is the part that I don't understand in the backend PHP usage.
Your flow should be like this -
Mobile -> BackendServer(PHP) -> APNS server -> Notifications->Back on device.
User will submit her/his criteria to server then server will process on that and send request to APNS server.
The APNS server will send remote notification on her/his device based on criteria requested.

Receive update from web server to iOS App and synchronize data

i'm writing an app that manage a sqlite database, and i have write a web server, i want the user register in my web server with username and password, i already know how make a request from ios app to server and receive the response, but i want enable also the synchronization of the sqlite database to other device, i now that with core data i can use iCloud synchronization, but for now i prefer use sqlite, and find a way to synchronize it, for example i want create this:
make a change in the sqlite in the iPhone app;
the app send this change to the server for that user;
then the server have to send this update to other device connected at that user;
and now i can't go over, how the server can send this change to the other device? the device has to be always listen to the server? or there is a way to send this update directly to some device and handle it? like an apple push notification?
EDIT: if it's possible use an apple push notification to do this, i doesn't want alert with text sound and badge the user, but send a "silent notification" it's possible?
As a high-level there are a few different ways to approach this, all of which have pros and cons. Two name two examples you can do a polling method, active push or a hybrid approach.
Polling: at some pre-determined interval the app tries to "phone home" and send the delta db changes up to the server. Here you know that your server will be expecting X number of responses in any given interval so you can appropriately gauge your load.
Active Push: The user decides when they want those changes to be transmitted to the server by hitting a "Sync" button. This allows the user to only push data back up to the server when they know there's a change but an over zealous user may make a change, upload, make a change, upload, etc instead of queueing up a bunch of changes and sending them all at once. This may create frequently unneeded server calls.
Hybrid: You setup a polling schedule within the app AND give the user the ability to Sync at-will in the event there is a critical change that needs to be made ASAP.
Regarding the listener side of the equation you face a similar challenge conceptually. If the original user makes 20 changes and presses Sync 20 times do you bombard the second user's device 20 times as well or do you queue those changes up and send them down every 5 minutes (as an example)? Unless you have both devices paired to each other or are connected to the same network AND visible to each other via your app you're going to need to leverage that back-end server. Push notifications can be very useful in this manner but there is extra development and setup overhead to take into account to properly implement them.
To boil this all down I would recommend laying out what YOU want your syncing model to look like before you start marching down a path.

email sent status from rails or actionmailer

I am developing a test application and running the whole thing on my work pc. I am using my corporate mail server to send mails. It works fine normally. I was wondering how to handle any conditions like if the mail server is not reachable from my pc.
As far as i have read about it, the rails application just sends the mail and that's it. There is no way to know if the mail reached the recipient, if the recipient mail id was correct etc.
Any thoughts on how to handle this scenario?
Thanks and Regards,
Anjali
I believe you're mixing together two problems here, those are quite unrelated really.
First problem - making sure that the email was accepted by the corporate mail server (that is mail relay in this case). To solve this you can either build a local queue of messages (store them in the database, queue server, whatever) - and send them with a separate worker process, that will pull each message from a queue, try to deliver it and delete it only if it was accepted by the mail relay.
Or, if you don't need low-level manual control of the process, you can set up a simple local mail server on your machine and instead if sending emails directly to your corporate mail relay, just give them to your local mail server. It will then make sure that the emails were delivered to the corporate properly.
But in both cases you won't get any info about where the message was delivered to the final recipient - like whether the email address was valid, user's mailbox was not full, etc.
Second problem - track mail delivery errors. To properly and completely solve this problem you need to catch all mail bounced back to you from the remote servers and analyze it, as many errors are unknown at the moment when the email is send - but they come back later in the form of mail bounces. If you catch and track these bounces you'll be able to catch errors likefull mailboxes, invalid emails, just temporarily delivery failures, etc.
It's the way it is done in mail lists management software - for example, phpList operates in exactly the same way.
I thought about this problem. My thought was to store the message into a separate model called "mailqueue" and then run a ruby script that will pull and delete a message from that mailqueue only if the corporate mail server is available (which I already have the code to do that, I believe). Of course, if there is a better way, I would welcome it as well.

Resources