Here's one way:
public void sendMail(String fromAddress,
String recipients,
String subject,
String content,
String contentType,
String smtpHost,
int smtpPort,
String username,
String password) {
try {
Properties props = System.getProperties();
Session session = Session.getDefaltInstance(props,null);
MimeMessage message = new MimeMessage(session);
message.setFrom(fromAddress);
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients, false));
message.setSubject(subject);
message.setContent(content,contentType);
message.setSentDate(new Date());
Transport transport = session.getTransport("smtp");
transport.connect(smtphost,smtpPort,username,password);
transport.sendMessage(message,message.getAllRecipients());
transport.close();
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
I don't like that way, because it's no good for anything but sending via an SMTP server with password based authentication. So, if I want to send e-mail through an SMTP server that has, say, a white-listed IP policy so I don't need to provide authentication, I have to write a whole new function that will duplicate a significant part of that code. Also, that long list of arguments to the function is just ugly, but it's what you're stuck with if you abstract a function that's hard-coded for SMTP password authentication.
Here's a better way, that is abstracted nicely:
public void sendMail(Properties props,
Authenticator authenticator,
String fromAddress,
String recipients,
String subject,
String content,
String contentType) {
try {
Session session = Session.getDefaultInstance(props, authenticator);
Message message = new MimeMessage(session);
message.setFrom(fromAddress);
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients, false));
message.setSubject(subject);
message.setContent(content,contentType);
message.setSentDate(new Date());
Transport.send(message);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
The function above can be used to send e-mail with all sorts of configurations. All you have to do is pass it the
Properties and, if you need to, an instance of a class extending javax.mail.Authenticator. Here's an example to send an e-mail identical to the first example above:
Properties props = System.getProperties();
props.put("mail.smtp.host","smtpHost");
props.put("mail.smtp.port","smtpPort");
props.put("mail.smtp.auth","true");
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username","password");
}
};
sendMail(props,auth,"no-reply@mysite.com","user@site.com","Hello World","Wow, big world.","text/plain");
And, to send an e-mail without authentication (as in the IP white-list policy):
Properties props = System.getProperties();
props.put("mail.smtp.host","smtpHost");
props.put("mail.smtp.port","smtpPort");
sendMail(props,null,"no-reply@mysite.com","user@site.com","Hello World","Wow, big world.","text/plain");
The great part is that the function sending the e-mail doesn't need to know anything about how it's going to do it, since the configuration is entirely passed in as arguments via the session and the optional authenticator. There is, however, a catch that I've noticed has tripped people up all over the internet. The values you set to your
Properties object must all be of class String. For example, this works
Properties props = System.getProperties();
props.put("mail.smtp.host","mail.mysite.com");
props.put("mail.smtp.port","587");
props.put("mail.smtp.auth","true");
Whereas, this does not:
Properties props = System.getProperties();
props.put("mail.smtp.host","mail.mysite.com");
props.put("mail.smtp.port",587);
props.put("mail.smtp.auth",true);
It doesn't matter that the values for
mail.smtp.port and mail.smtp.auth are an int and a boolean, respectively. If they are not specified as a String, Transport.sendMessage(message) will fail.* As a disclaimer, I typed the above code, rather than copy and paste from a program I've compiled, so I apologize if there's a typo anywhere up there that prevents it from compiling.

1 comments:
FYI, JavaMail 1.4.2 was enhanced to handle properties that aren't Strings.
Post a Comment