PKCLsoft
Where great things start…
  • Home
  • Blog
  • Money Up Credits
  • Crazy Balloons – Word List Gallery
  • Tap Times Tables
    • Times Tables Reports
    • Reviews
    • Suggestions and Credits
  • uAlertMe for iAlertU
    • Using uAlertMe for the first time
    • Network Settings
    • Other settings
    • Ready to Connect
    • Connected!
    • Configuring your Mac
  • Support
    • Crash reporting
  • Privacy
    • COPPA in the US
  • World of Hex Press Kit
Select Page ...

PKCLsoft

Java Send Mail Client

pkclsoft May 6, 2011 ialertu jsendmail mail client, ualertme iphone

For some time now I’ve been working on the open-source project called iAlertU, found at: sourceforge.net/projects/ialertu/.


One of the first things I did on the project was change the way it sent email.  I didn’t like the dependence on the user having to use Apple Mail for their email.  I guess I’m a Thunderbird user from way back.


A lot of people these days just use online email such as Gmail.  I do, if for no other reason than their wonderful anti-spam filters.


So, in order to make iAlertU independant of any specific email client, I wrote what started out as a fairly simple client in Java.  This started out as a snippet of example code from Sun, that was integrated into my PortaBill application, but over the past year or so, it has grown a bit in complexity in order to meet the needs of iAlertU and the growing community of Mac users out that that are installing it.


As users of iAlertU have pointed out weaknesses in the email client due to the many and varied email configurations, jsendmail has grown in features. It’s still only a single Java class, and it’s not a lot of code, but it represents many hours of searching and debugging to try and get a client that can do everything I need.


jsendmail is a simple console application.  iAlertU runs it behind the scenes, passing arguments to tell it where to find the email body and any images that need to be sent.  It can also be used independently.


The original command syntax was modelled on mini_sendmail, and similar linux client that I use occasionally.


So, with the gentle prompting of an iAlertU user, I decided to post the code here.  If there’s enough interest, I’ll put it on sourceforge.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
* @author Peter Easdown
* http://www.pkclsoft.com
* @version 1.1
*
*/
public class JSendmail {

private static final int SMTP = 0;
private static final int SMTPS = 1;

private static Vector ccList = new Vector();
private static Vector attachmentList = new Vector();
private static String toAddr;
private static String subject;
private static String serverName;
private static File messageFile;
private static InputStream input;
private static String username;
private static String password;
private static String fromAddress;
private static String contentType;
private static int serverPort = -1;
private static int smtpMode = SMTP;

private static final String SMTP_TITLE[] = {"smtp", "smtps"};

/**
* Validates command line parameters and executes main function if valid.
*
* @param args - The command line parameters
*/
public static void main(String[] args) {
// Process the arguments.
if (args.length < 5) {
printUsage("Too few arguments.");
}

int argIndex = 0;

while ((argIndex < args.length) && (serverName == null)) {
if (args[argIndex].equals("-f")) {
argIndex++;

if (messageFile != null) {
printUsage("Only one instance of \"-f\" option allowed");
} else if (argIndex < args.length) {
messageFile = new File(args[argIndex]);

if (!messageFile.exists()) {
printUsage("-f filename <" + args[argIndex] + "> does not exist!");
}

argIndex++;
} else {
printUsage("-f requires filename parameter");
}
} else if (args[argIndex].equals("-s")) {
argIndex++;

if (subject != null) {
printUsage("Only one instance of \"-s\" option allowed");
} else if (argIndex < args.length) {
subject = args[argIndex++];
} else {
printUsage("-s requires string parameter");
}
} else if (args[argIndex].equals("-c")) {
argIndex++;

if (ccList.contains(args[argIndex])) {
printUsage("CC address: " + args[argIndex] + " is specified more than once");
} else if (argIndex < args.length) {
String newAddr = args[argIndex++];

if (newAddr.indexOf('@') == -1) {
printUsage("CC address is invalid, must contain \"@\"");
}
ccList.add(newAddr);
} else {
printUsage("-c requires string parameter");
}
} else if (args[argIndex].equals("-a")) {
argIndex++;

if (attachmentList.contains(args[argIndex])) {
printUsage("attachment: " + args[argIndex] + " is specified more than once");
} else if (argIndex < args.length) {
File newAttachment = new File(args[argIndex]);

if (!newAttachment.exists()) {
printUsage("attachment: " + args[argIndex] + " does not exist.");
} else if (newAttachment.isDirectory()) {
printUsage("attachment: " + args[argIndex] + " must not be a directory.");
} else {
attachmentList.add(newAttachment);
}

argIndex++;
} else {
printUsage("-a requires string parameter");
}
} else if (args[argIndex].equals("-u")) {
argIndex++;

if (username == null) {
if (argIndex < args.length) {
username = args[argIndex++];
} else {
printUsage("-u requires string parameter");
}
} else {
printUsage("-u may only be specified once");
}
} else if (args[argIndex].equals("-p")) {
argIndex++;

if (password == null) {
if (argIndex < args.length) {
password = args[argIndex++];
} else {
printUsage("-p requires string parameter");
}
} else {
printUsage("-p may only be specified once");
}
} else if (args[argIndex].equals("-sp")) {
argIndex++;

if (serverPort == -1) {
if (argIndex < args.length) {
try {
serverPort = Integer.parseInt(args[argIndex++]);
} catch (Exception e) {
printUsage("-sp requires integer parameter");
}
} else {
printUsage("-sp requires integer parameter");
}
} else {
printUsage("-sp may only be specified once");
}
} else if (args[argIndex].equals("-ct")) {
argIndex++;

if (argIndex < args.length) {
contentType = args[argIndex++];
}
} else if (args[argIndex].equals("-ssl")) {
argIndex++;

if (smtpMode == SMTPS) {
printUsage("-ssl may only be specified once");
} else {
smtpMode = SMTPS;
}
} else if (args[argIndex].equals("-from")) {
argIndex++;

if (fromAddress == null) {
if (argIndex < args.length) {
fromAddress = args[argIndex++];
} else {
printUsage("-from requires string parameter");
}
} else {
printUsage("-from may only be specified once");
}
} else if (toAddr == null) {
toAddr = args[argIndex++];

if (toAddr.indexOf('@') == -1) {
printUsage("send to address (" + toAddr + ") is invalid, must contain \"@\"");
}
} else if (serverName == null) {
serverName = args[argIndex++];

if (fromAddress == null) {
fromAddress = System.getProperty("user.name") + "@" + serverName;
}
}
}

if (messageFile != null) {
try {
input = new FileInputStream(messageFile);
}
catch (FileNotFoundException e) {
printUsage("Unable to open file: " + messageFile.getPath());
}
} else {
input = System.in;
}

if (username == null) {
// Default the username.
//
username = System.getProperty("user.name");
}

if ((toAddr == null) || (serverName == null) ||
(username == null) || (password == null)) {
printUsage("Not enough arguments");
}

if (serverPort == -1) {
serverPort = 25;
}

if (contentType == null) {
contentType = "text/plain";
}

new JSendmail();
}

private static void printUsage(String reason) {
System.out.println("JSendmail: " + reason);
System.out.println("");
System.out.println("JSendmail usage:");
System.out.println("");
System.out.println("");
System.out.println(" JSendmail [-f filename] [-s \"str\"] [-c ccaddress] [-a attachment]");
System.out.println(" [-from fromaddress] [-u username] [-p password]");
System.out.println(" [-sp port] [-ssl] toaddress viaserver \"text\"");
System.out.println("");
System.out.println(" -f filename - Specifies that the text of the message be read from the file \"filename\" instead");
System.out.println(" of standard input.");
System.out.println(" -s \"str\" - Specifies the subject of the email to be sent.");
System.out.println(" -c ccaddress - The email address of some to add to the CC list.");
System.out.println(" -a attachment - The path of an attachment to add to the email.");
System.out.println(" toaddress - The email address to which the email will be sent.");
System.out.println(" viaserver - The hostname of the mail server via which the email will be sent.");
System.out.println(" -u username - the username with which to authenticate, defaults to currently logged in username.");
System.out.println(" -p password - the password with which to authenticate.");
System.out.println(" -sp port - the port number to connect with.");
System.out.println(" -ssl - Instructs jsendmail to use SSL when connecting to the SMTP server.");
System.out.println(" -ct type - the content type of the email, defaults to \"text/plain\"");
System.out.println("");
System.out.println(" \"text\" - the actual text of the message as read from standard input.");
System.out.println("");
System.out.println("Note that if no -fromaddress option is specified, then the currently logged in username is used");
System.out.println("in the form @viaserver.");
System.out.println("");
System.exit(1);
}

private JSendmail() {
Properties props = System.getProperties();
// Set up the mail server.
props.put("mail." + SMTP_TITLE[smtpMode] + ".host", serverName);
props.put("mail." + SMTP_TITLE[smtpMode] + ".auth", "true");
props.put("mail.smtp.connectiontimeout", "120000");
props.put("mail.smtp.timeout", "120000");
props.put("mail.smtp.starttls.enable", "true");

boolean sent = false;
String reason = null;

Session session = Session.getInstance(props, new SMTPAuthenticator(username, password));
//session.setDebug(true);

// Create a new message --
Message msg = new MimeMessage(session);

// Set the FROM and TO fields --
try {
try {
msg.addFrom(new Address[] {new InternetAddress(fromAddress, fromAddress.substring(0, fromAddress.indexOf('@')))});

msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
toAddr,
toAddr.substring(0, toAddr.indexOf('@'))));
msg.setReplyTo(new Address[] {new InternetAddress(fromAddress, fromAddress.substring(0, fromAddress.indexOf('@')))});

// -- Set the subject and body text --
if (subject != null) {
msg.setSubject(subject);
}

if (ccList.size() > 0) {
for (int i = 0; i< ccList.size(); i++) {
String ccAddr = (String)ccList.elementAt(i);
msg.addRecipient(Message.RecipientType.CC, new InternetAddress(ccAddr, ccAddr.substring(0, ccAddr.indexOf('@'))));
}
}

// -- Set some other header information --
msg.setSentDate(new Date());

byte[] bytes = new byte[input.available()];
input.read(bytes, 0, input.available());

if (attachmentList.isEmpty()) {
msg.setContent(new String(bytes), contentType);
} else {
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();

// Fill the message
messageBodyPart.setContent(new String(bytes), contentType);

Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);

// Part two is attachment
for (int i =0; i < attachmentList.size(); i++) {
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(attachmentList.elementAt(i));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(attachmentList.elementAt(i).getName());
messageBodyPart.setHeader("Content-ID","");
multipart.addBodyPart(messageBodyPart);
}

// Put parts in message
msg.setContent(multipart);
}

msg.saveChanges();

Transport trans = session.getTransport(SMTP_TITLE[smtpMode]);

try {
// -- Send the message --
trans.connect(serverName, serverPort, username, password);
trans.sendMessage(msg, msg.getAllRecipients());
} finally {
trans.close();
}

sent = true;
} catch (UnsupportedEncodingException e1) {
sent = false;
reason = e1.getMessage();
} catch (IOException e) {
sent = false;
reason = e.getMessage();
}
} catch (AddressException e) {
sent = false;

if (e.getMessage() != null) {
reason = e.getMessage().trim();
} else if (e.toString() != null) {
reason = e.toString();
} else {
reason = "Unknown";
}

if (e.getCause() != null) {
reason = reason + "\n" + e.getCause().getMessage().trim();
}
} catch (MessagingException e) {
sent = false;

if (e.getMessage() != null) {
reason = e.getMessage().trim();
} else if (e.toString() != null) {
reason = e.toString();
} else {
reason = "Unknown";
}

if (e.getNextException() != null) {
if (e.getNextException().getMessage() != null) {
reason = reason + "\n" + e.getNextException().getMessage().trim();
}
}

if (e.getCause() != null) {
reason = reason + "\n" + e.getCause().getMessage().trim();
}
}

if (!sent) {
System.out.println("JSendmail unable to send: " + reason);
System.exit(1);
} else {
System.exit(0);
}
}


public class SMTPAuthenticator extends Authenticator {
private PasswordAuthentication authentic;

public SMTPAuthenticator(String username, String password) {
authentic = new PasswordAuthentication(username, password);
}

public PasswordAuthentication getPasswordAuthentication() {
return authentic;
}
}
}






Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Facebook (Opens in new window)

Related

← iWeb Duplicate Image Optimization
uAlertMe – the good the bad and the ugly →
pkclsoft

You can add widget to "blog" widget area by going to Appearance > Widget

Copyright © 2012 pkclsoft.com. All Rights Reserved