A good example of Ubuntu email handling for a rails project - ruby-on-rails

Having issues with a rails 2.2.2 app running on a VPS (Ubuntu 8.10): looking for github repos, posts, anything that covers the right way of setting up email processing. For example, should it be using sendmail or smtp?

This is not Ubuntu-specific.
Configuring the sending of mail doesn't really have a "correct" answer. If you have sendmail working upon your machine (so that "mail foo#bar.com" works) then use that.
If you have an SMTP server running locally, which works, then use that.
The more specific answer really depends on you saying:
What did you try?
How did it fail?

Are you looking to send or receive email (or both)?
The answers will be different in each case, and may (or may not) include configuring a mail server on the VPS.
If you need to configure a mail server the best guides (extensive and step by step) I found are those from slicehost that you find here: Mail server setup and configuration
If you need to just receive emails the best thing is to avoid installing a mail server and let your service provider (or Moogle) handle the incoming email.
Then you have to write some code to fetch those emails form the POP or IMAP server and feed them to the incoming mail handler (which typically is based on ActionMailer). One easy way to write the fetching code is to use the fetcher plug-in which incorporates the following common pattern of interaction with the mail server:
Connect to a remote server (POP or IMAP)
Download the available messages
Process each message (passing it to another object)
Remove all downloaded messages from the remote server
you need to create an instance of the class Fetcher passing the class of the object that will process the emails (plus any other configuration parameters that are needed), then calling the fetch method will execute the steps 1 to 4 above.
The plug-in is on Github: http://github.com/look/fetcher/tree/master and you can use it both to build a daemon (i.e. a process which stays in a loop polling the mail server for new messages), or to write a batch file to be run from cron (taken from the plug-in docs):
begin
Lockfile.new('cron_mail_fetcher.lock', :retries => 0) do
config = YAML.load_file("#{RAILS_ROOT}/config/mail.yml")
config = config[RAILS_ENV].to_options
fetcher = Fetcher.create({:receiver => MailReceiver}.merge(config))
fetcher.fetch
end
rescue Lockfile::MaxTriesLockError => e
puts "Another fetcher is already running. Exiting."
end

Related

Writing a spec for sending a mail via API

I want an E-Mail to be sent using a background process whenever an Invite was generated.
What I currently have is this approach: The Invite model has the method send_mail, which sends an E-Mail using the Mandrill API and gem. It also has the method queue_mail adds InviteMailer with the invite's ID to the queue using Resque.
However… Since I'm having sort of a really hard time writing specs for this, I assume this might not be the best approach to send mails.
What I mainly want and need to test:
was the mail added to the queue?
is InviteMailer working properly?
does the mail contain the correct vital information?
Vital informations are: sent to the correct person, contains a link to a specific site and some specific data/text; also I'm not sure how to get the current host to the link.
I don't think this is a rare thing to do, so I wonder what the best practices are.
My testing environment: rspec, capybara, factory girl. I already added VCR, to cache the API-request.
You can use Mailcatcher to fake your mail server, and check received mail via web API:
Features
Catches all mail and stores it for display.
Shows HTML, Plain Text and Source version of messages, as applicable.
Rewrites HTML enabling display of embedded, inline images/etc and open links in a new window. (currently very basic)
Can send HTML for analysis by Fractal.
Lists attachments and allows separate downloading of parts.
Download original email to view in your native mail client(s).
Command line options to override the default SMTP/HTTP IP and port settings.
Mail appears instantly if your browser supports WebSockets, otherwise updates every thirty seconds.
Growl notifications when you receive a new message.
Runs as a daemon run in the background.
Sendmail-analogue command, catchmail, makes using mailcatcher from PHP a lot easier.
Written super-simply in EventMachine, easy to dig in and change.
How
gem install mailcatcher
mailcatcher
Go to http://localhost:1080/
Send mail through smtp://localhost:1025
API
A fairly RESTful URL schema means you can download a list of messages
in JSON from /messages, each message's metadata with
/messages/:id.json, and then the pertinent parts with
/messages/:id.html and /messages/:id.plain for the default HTML
and plain text version, /messages/:id/:cid for individual
attachments by CID, or the whole message with /messages/:id.source.

Kinda-mass emailing from Rails, but with own mail server

I've read most of the other answers on this topic, but a lot of them related to either third-party services like MailChimp (which I'm not necessarily opposed to) or how not to upset the host's email server.
I believe this case is unique so that it'll contribute...
I have my own DigitalOcean droplet running a rails app. I need to send out 100-1000 emails every so often, each with a unique message (a link I'm using for tracking clicks originating from the email).
I'm also operating my own iRedMail server.
Can someone recommend how to best-handle this task? I was going to simply cycle through the list of emails and use the template.html.erb to drop in my link, but what types of problems might I run into?
Thank you!
You should decouple your Rails App from the mail sending so that you don't have to wait in your view for the mails to be sent (assuming that you click on something that triggers the start of your mail sending). Use something like delayed_job or another queueing mechanism that Rails offers and only queue up the sending job of the e-mails. Then when the queue comes to execute the particular job you can customize the message with an HTML part and a text part or whatever else you need and pass them on individually to your MTA.

Running a PHP script on email arrival in an IMAP Server

I'm trying to implement a webmail in PHP. I would like to write a PHP CLI script which is run on every email arrival to store some parts of (not all of) incoming email into database for search purposes. Then when the user finished searching and chose an email to show, a connection is made to mail server to retrieve the complete email. In order to implement this scenario I need to make some sort of connection among emails within database and mail server.
Since my knowledge of working with mail servers is limited to Zend Framework's API, what I believe I need in order to retrieve an email from an IMAP server is a message number or a message unique id (this later one seems not to be supported by all mail servers).
To this point, I've managed to find .forward (and some other ways) to introduce my PHP CLI script to MTAs to be run on every email arrival. This way I can store emails to database. But this won't do since message unique id is created by MDA so MTA do not know of it and they can not provide it to me. This means I can not find emails later when I want to retrieve them from mail server.
At last, here's my question: Is there a way to introduce a PHP CLI script to a MDA for emails' arrival? If this is dependent on the mail server, which servers do support this and how? My personal choice would be Dovecot or Courier, but any other mail server would do as well.
This is tricky -- there are many ways on how to setup delivery. Some of them work with the underlying mail store directly, bypassing your IMAP server altogether, while others use e.g. Dovecot's facilities.
Have you considered building on top of the notify plugin which ships with Dovecot?
It seems like it's impossible to introduce such a PHP CLI script to IMAP server (at least I'm sure of Dovecot). Anyway, the work around I found for this problem is to use my own PHP script to insert the new mails into IMAP server and retrieve their id's and then store the id in database for future references. To be clear, email are given to my PHP CLI script by MTA, not MDA. As I said before this is done easily using .forward file.
[UPDATE]
Unfortunately it seems this solution can not be implemented as well. The way to insert a new email to IMAP server is APPEND command, and to have the UID of the recently added mail server must support UIDPLUS extension. Neither Dovecot nor Courier supports this extension at the moment! If they did it seems the server would return the UID with a APPENDUID response.
[UPDATE]
It is my bad since Courier does support UIDPLUS. So this solution is valid and the one I'm going to implement.

Creating an e-mail parser as a service?

I am trying to hash out how I would create an e-mail parser. I understand technically how to do it, but I cannot figure out implementation details.
So, user sends an e-mail to an address, mail server receives and my app parses it based upon subject, content and drops it in a bucket (e-mail account or database) and then I can act upon it.
So do I use an existing mail server software (like Zimbra, which we already have running) or do I create an app that listens on port 25 and does specifically what I need? (meaning no mail server sofware running on this box, etc)
My goal here is to create myself a series of organization tools for personal use in an automated way based upon what I e-mail myself.
Writing something to listen on port 25 and act as an SMTP server will be involved and probably overkill for what you want.
I think there are two main options. The first is to leave your existing mail server in place and then poll an account on that mail server over IMAP (or POP3) to retrieve the emails and then process them using a script. It really doesn't matter what language you're comfortable with as there are libraries for handling IMAP connections and then parsing the email in most languages.
Alternatively you could look at a service like http://CloudMailin.com that does this for you. It will receive the email and send it to a web app that you could create via an http post in something like JSON format.
I would go for a python script which polls the mailbox (basing on a cron job). Python allows you to access IMAP very easily and has powerful regular expression functions to parse the email content.
Try something like:
import imaplib, email
import re
M= imaplib.IMAP4_SSL('imap.gmail.com')
M.login('user', 'pass')
M.select('Imap_folder')
typ, data = M.search(None, 'FROM', '"*"')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
email_body = data[0][1] # getting the mail content
mail = email.message_from_string(email_body) # parsing the mail content to get a mail object
foo = re.compile("your regular expr here", re.MULTILINE)
res = foo.search(email_body)

Receive mail in Ruby/Rails

How would i go about to receive mails in a Ruby on Rails application without going through a mail server like PostFix or to fetch them by pop3 etc.
What i was to do is to catch all mails sent to #mydomain.com and just do something with them in my application. I don't need to store the mails or anything like that.
Is this posible?
I just implemented this for my SAAS to autoprocess mailer-bounce notification messages.
Call me, call you?
You call me
You can set up a local mail server. It would then respond to an incoming email, and start up a rails executable to process the email. This method is NOT recommended since starting up rails is a big task (takes multiple secs and lots of memory). You don't want a Rails bad boy started up just because you received an email. You'd be writing your own DDOS attack. (Attacking yourself.)
I call you
Instead, poll for email on your own schedule by using a single job to process all currently waiting emails. You need to set up a background job handler since stock rails is focused on responding to web requests. I use delayed_job, but there are other alternatives including kicking off a cron job every so in often.
Another benefit is that you don't need to manage a mail server. Leave that headache to someone else. Then use the Ruby library net::imap to read the incoming mail and process it.
If your process doesn't recognize the email format, then forward the msg to a human for processing.
And be sure that if the process sends mail in addition to reading/processing it, that the process uses a different email address as its From address. Otherwise, odds are good that sometime along the way, you'll end up in an email loop and many gigabytes of messages going back and forth. For example, your process receives a message, responds to it, but in the meantime the sender (a human) has switched on vacation response. And your robot then responds to the vacation response..... oops....
Writing your own mail server
Re:
How would i go about to receive mails in a Ruby on Rails application without going through a mail server like PostFix or to fetch them by pop3 etc.
What i was to do is to catch all mails sent to #mydomain.com and just do something with them in my application. I don't need to store the mails or anything like that.
Direct answer: Yes, you could do this by writing an smtp server and setting up dns so your machine will be the mail destination for the domain. Your smtp server would process the messages on the fly, they would not be stored on your system at any point.
Is this a good idea? No, not at all. While appearances may be to the contrary, email is a store and forward system. Trying to avoid storing the messages before your app processes them is not smart. It would be a very very poor "optimization." However, using an access protocol (POP3 or IMAP) is a good way to avoid the costs of installing, configuring and managing a mail server.
You can do this if you write your own mail server, or if your mail server supports hooks to run external programs upon receipt of mail (e.g. procmail).
If you don't have procmail available (or, if on something like Exchange Server, don't feel like writing custom rules or extensions), you're simply better off using a pop3 library to fetch mail.
Obviously, writing a mail server is more difficult than any of the alternatives.
If you're mostly worried about checking potentially hundreds of email accounts, that's solvable by configuring your email server properly. If you're on a hosted provider, ask your server administrator about creating a "catch-all" account that routes all mail to unknown addresses to a single account.
If you're aiming to avoid having to poll a server, consider the IMAP IDLE command. I've successfully written a Ruby client that opens a connection to an IMAP server, and gets told by the server when new mail arrives.

Resources