-
Notifications
You must be signed in to change notification settings - Fork 0
Home
RobustMail is a mail delivery service, that allows abstraction between multiple mail delivery providers and improves the reliability of message delivery by employing a failover mechanism in case some of the underlying services is unavailable.
- Messages will be sent by the instance owner or its trusted associates to conduct their relevant communication. Identification of spamming behavior is out of service scope.
- Message delivery is important - successful delivery is favored over latency, losing 200 ms or more of queued messages does not fulfill the acceptance criteria.
- Non-repudiation is out of scope - the service makes best effort to suggest recipient address correction and deliver the message to the proper mail provider and assumes that it will handle it properly, not when or whether the recipients have opened it.
- Install the project requirements with pip install -r requirements.txt
- Export your relevant api keys and login data as per settings.py (RabbitMQ, Redis, Mailgun, SendGrid)
- Test it with nosetests
- Run the application with python RobustMail.py
- Try the REST API
- /api/send-message Accepts POST
Accepted fields
- sender- *(required)* The sender of the email
- name (optional)
- email *(required)*
- subject - The subject of the email
- recipients[] - *(required)* array of recipients
A recipient consists of:
- name (optional)
- email (required)
- cc [] (optional) array of carbon copy recipients
A recipient consists of:
- name (optional)
- email (required)
- bcc [] (optional) array of bcc recipients
A recipient consists of:
- name (optional)
- email (required)
- text - *(semi-required)* if body is NOT set, this is required. This is the text representation of the message. You may choose to have both.
- body - *(semi-required)* if text is NOT set, this is required. This is the html representation of the message. You may choose to have both.- Example responses
{ "success": true, "message" : "Message accepted for processing!" }
{ "success" :false, "message" : "Text or body is required" }
{ "success" :false, "message" : "Sender email invalid" }- /api/validate-email Accepts POST
- email *(required)* The email address to be checked- Example responses
{ "success": true, "message" : "Syntax and domain accepted" }
{ "success" :false, "message" : "Address domain not found" }
{ "success" :false, "message" : "Address syntax invalid" }
The service is accessible through an API or simple Front-end. Upon receiving a message via the REST service, it is validated and if accepted enters the RabbitMQ powered Celery task queue which passed it to the MessageService. It takes care of managing message providers and which one to process the message. This simple design allows retrying providers in case some of them are unavailable and also improves the reliability in case the service itself is restarted, because of the RabbitMQ nature. Syntax-wise and MX record validation is available for emails.
Celery is listed as a non-functional requirement for asynchronous processing. Celery supports multiple message brokers, but the best supported, widely used and recommended by Celery are:
Redis is a high-performance message broker and supports most of the features. However as per its official persistence documentation http://redis.io/topics/persistence it favors low latency over keeping the latest written data in case of service failure and the recommended mode to improve that is AOF with fsync every second. They also list potential issues with the append-only mode. Redis will be used as result backend when results are needed, because of its good performance and for reducing CloudAMQP message consumption.
RabbitMQ is the recommended solution, it is widely deployed, tested and supports all features, including delivery acknowledgments. Focuses on reliability, however allows multiple configurations to improve performance. It also includes management and monitoring solutions. For the prototype purpose gossiping and mingle are disabled to fit the app in the CloudAMQP quotas.
A modern mail delivery provider has relatively low server failure rates, so it is assumed that the service owner has a preferred mail provider with high message sending quota and keeps the additional services with lower quotas for failover. The provider priority algorithm tries to send the message with the top preferred provider that is assumed available. In case that fails, the provider is retried after a fixed time, preference considered. In case all providers are unavailable, waiting time until the next retry is applied. This simple approach allows a good balance between time to return to the primary service and requests count in case of service failure.
Completing this step quickly being a priority, Heroku was chosen as a Cloud platform and Travis CI as a continuous integration tool. They have free versions and integrate pretty seamlessly with Github and with each other, while keeping the boilerplate code to a minimum. Heroku supports all of the products required for the development natively
Support for complex messages, rich text editor, file upload etc.
Add HTTPS for the application, login for senders in the front end, api keys for the REST API
Implement load tests, use a noreply email as a recipient
.