Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
by
Lessons:14Length:2.4 hours
  • Overview
  • Transcript

2.10 Sending Email

We’ll follow up the previous lesson by introducing an email notification to commenters when a task is marked as done. In this lesson, you’ll learn all of the main aspects of sending email with Rails.

Related Links

2.10 Sending Email

Let's continue with what we were developing in the previous lesson. If you recall correctly, we were able to toggle between the done and undone state for each task. If I click on it, you will see a small highlight, and the task will be updated as being not done. If I check it again, this will be updated. Now, I want to show you the power of using email in your rails application. And to do that, we're going to pick up on this specific feature. Whenever we tick a check box for one task, we want to send an email to whoever is part of that task. So if I click on the details for that task, you will see that we have this user with one user name. In fact, in order to allow to view that email address, I'm going to change the template. So let's go to app views, then tasks, then show. The show template contains the list of all of the comments. So in here, I'm going to create for example a small text so we'll type in small and then print out the comments email. So you just type in comment.email. The comment is a comment object which has an email attribute. You simply call that method, and it will print out the proper value. Going back to the browser and hitting reload, you will see that e-mail in specific. Our objective is to send an e-mail to whoever has participated in the list of comments. In this case if we send an e-mail, this address will be the only one affected, which is fine for me. Now how does Rails work in order to send e-mail? What should we do about it? Well the way we do it is by calling a generator in Rails, so we'll go ahead and step to the terminal. Let's type in rails generate and then a mailer. A mailer takes a name and a list of methods. Each method represents a specific context about which to send an e-mail. So I'll create a default mailer because most likely we won't be using an other e-mail settings, at least as of now. So I'll create a default mailer and the context that I want to add is called confirm task basically this will make sure that whoever is participating in that task gets a confirmation email that the task was marked as done or not done. Let's press Enter and see the result. You will see a mailer class, here, a default application mailer, this is basically a parent class, a super class, then a bunch of different views and some test files. We're gonna focus our attention on the default mailer, and on these two. These are the layouts we won't be needing to handle those as of now. You are totally free to browse them, if you wish to, to perform some changes you would like. But really we're going to focus on the confirmed task templates, the text version and the HTML version. Okay, with this we can browse through them and see what we should do in the mails folder you will see the two files. The application mailer has a default instruction and a default layout. I'm going to change this default address to my own commercial address for Tutsplus. Now the default mailer will use the settings from this application mailer because it inherits from it. As for the confirm task method, we will use this method to define the contents of the email. Whatever instance variables we set in the method, will be used in the templates. So, I'm going to remove this greeting method, and the to argument in the mailing instruction will contain the list of all emails within the list of comments. Now, how do we access them, really? Well, the confirm task method will take a task as an argument, so from that object we can reach the list of comments and from there we can create a mapping. So, I want to use the map function and specifically return all of the emails, so we use this instruction. By the way this is the same as typing something like task.comments.map {, which takes each different comment as an argument, and then retrieve the comment's email. This is the same as what's on top. Because we want to access a single message from each different object, we can use this notation. It makes it a lot simpler. Take a moment to absorb this. Okay, let's take two what we should do. We will get an array of different addresses, so that's more than appropriate. We want to send an email to all of them. Now about that subject. Curiously enough, you can see that we have an instruction regarding the subject of that email. We need to look up the internationalization file and pass the subject in there. Let's see, we need to go to config, locals and then en.yemo. This is the exact file, so I'm gonna go ahead and change it in order to add that subject. So let me just go back to the previous one, let's see, okay so the method that we need is this one. I'm just going to copy it, go back to the previous file and paste it right here. This is the string that it's going to be using. So I'm going to separate each different perimeter in between dots with a colon and for each one, there will be separate keys. This is a structure that Rails supports, so basically, we just need to follow it! In here, we can type in for example, Task updated. And that's it. Basically the subject is specified in the localization files rather than the mailer class itself. This way we can use different localization setting depending on where the use is located. For now, we're just going to stick to English. Now let's stick to the default mailer class. We already have a subject. And the list of addresses that are basically the recipient to the email. The only thing left is the templates, the body of that email. We need to go to views in the app folder, then choose default mailer, and then for each one of these templates we'll fill in the information for now, it has a default placeholder text which I'm basically going to remove. The same goes for the text version. Okay, now let's focus on maybe the text version first. We'll figure out a way of doing that in HTML as well. This is a valid example for a template. Remember, this is a text version only. So every new line counts. We're telling the user that he participated on the following task and will pass the tasks title. This is actually a good thing that I remembered. We need to set the instance variable properly and then we'll need to tell the user whether it is marked as done or undone. If the task is done, we'll tell the user that it's done. Otherwise, the other way around. That's as simple as that. We're gonna do the same thing for the other template. I pasted a snippet that closely resembles the text version. The same text is there, but we're just using regular HTML. So, the same text, but we'll add in a strong tack to the title. And then the previous text in the second line is basically the same thing as in the text version. So I'm just going to say this and we're ready to go. Well, wait a minute, you need to go to that default mailer and use that task variable and make so it is an instance variable, like so. This is very important, otherwise the content will not be there. In fact, you will throw some errors because the variable's not there. Now we still need to do two more things. One of them is to integrate the mailer with the actual code when we update the task, and the other one is to configure the email server. So let's go to the controller. On the tasks controller, let's see, here it is, when we try to update a task, so we're going to call the toggle method here, when we save the task, we're going to call that mailer. Let's use defaultmailer.confirm_task, which is the exact method we have we're gonna pass the task instance variable we have here and we'll call deliver later. There is an option called deliver now in case you want to deliver the email immediately. However, with Rails four, this is done via the deliver later method as well in case you don't have a job processor in the background, something like rescue or sidekick. So because we don't have any of that, the email will be delivered right away. However, if you do have such a service, and and want to deliver the email immediately, choose deliver_now. However, I think it's safer to use this method instead. It basically transfers the email process to another thread or another service and the request moves on immediately without delay. This is the instruction that actually sends the email. It resorts to the email class; use the method that's appropriate, in this case it's this one you're passing whatever arguments you feel you should have and then use the deliver method. The last thing that needs to be done is configure the mailer settings. We do that on an application level. So I need to go to the general configuration of the application. Specifically for each different environment you will most likely effect two specific environments the development on and the production one when you deploy it. We're going to star with development, but later on you can adjust your settings in development to mirror the best way to do it in production. Two things need to be considered. First of all, I want to make sure that I raise delivery errors so that we know whether something has gone wrong or not. If you were to keep this in false, you wouldn't know whether we had some errors in delivering the errors or not. So we're going to make that as a true condition. The other setting that we'll need to configure is actually not in here. So I'll type config.actionmailer.smtp settings. This is going to be a hash. So basically this will have some keys and values that will basically set up our SMTP configuration. Rails is not going to do anything whatsoever. It's just going to call SMTP and send an email from your own email address. Oh, by the way, we should add another instruction that tells up whether we should use SMTP or another delivery method. So use delivery method equals SMTP. Without this you won't be able to send email through SMTP, so you really should type that in. Now as far as the SMTP settings go I'm gonna paste a snippet of code that I prepared previously. There you go. You have five essential keys that you should point out. Specifically the address of DSNTP server. The username which is usually the email address itself. The password. The authentication method which should be log in, in case you use a user and password combo. And this instruction might be optional if you have, for example, some sort of a Gmail address or something like that. Usually, a mail server that's certified won't need this instruction. However, you might face that challenge in terms of the certificate not being valid or expired. And you'll need to set this option back to false. The reason I'm using environment variables is to hide my very own, personal information. So the SMTP_SERVER, SMPT_USER, and SMTP_PASSWORD variables will be defined in my own zshrc file. This is the best approach for increasing security. All of the data goes inside the computer in which the application is running. But still you're free to just type that string away. Just comment that out and type in the password, user name and address directly into the application. So let's just keep it like this. The information on these three fields are secure. We just need to test this out. Everything is set in place, so we just need to cut the server so that we can load all of these changes. So just type in real server again. So let's open the project page where the interaction takes place. Let's take the chance and open FireBug and reload this as we want to make sure that the A Check request comes in. Let's tick the box, and there you go. You could see the highlight message and everything. If the highlight doesn't appear, that means that something must have gone wrong, and you should check the error message that comes either in the Rail server, or in Firebug. But since the request came true, we successfully sent that email. As you can see, this is our email, it was sent today at this time so let me just double-click on that, and there you go. There's the email message. In this case it is just HTML, because you see this trunc tag and everything. The text is bold. So, great job on sending email. Let's sum this up really quick. You need to have the delivery method to SMTP. Make sure to raise delivery errors in development. And the SMTP settings should be something like this hash. The next step is to generate a mailer. You do that by typing railsgmailer. You will come up with an application mailer if it doesn't already exist. The default mailer is also their because that's the one that we generated with the appropriate method. After that you will need to configure your views so just go to the appropriate folder, assemble the content that you wish to put out to that user either in html or text formats. At the end just integrate that mailer with the application work flow. In this case just go to the task's controller, we wanted to send one e-mail each time we toggled a task and thus the result is as we just saw. Whenever we tick that check box and e-mail will pop up.

Back to the top