All Downloads are FREE. Search and download functionalities are using the official Maven repository.

base.email.Mail Maven / Gradle / Ivy

/**
 * Creative commons Attribution-NonCommercial license.
 *
 * http://creativecommons.org/licenses/by-nc/2.5/au/deed.en_GB
 *
 * NO WARRANTY IS GIVEN OR IMPLIED, USE AT YOUR OWN RISK.
 */
package base.email;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.List;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import base.email.encoding.Encoding;
import base.email.encoding.PlainTextEncoding;
import base.email.encoding.QuotedPrintableEncoding;
import base.text.Base64Encode;
import base.text.StringHelper;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/**
 * Deliver an email message via an SMTP server. Note this feature is
 * custom written because this facility does not always work out of
 * the box on all systems. Based upon but not fully tested against
 * RFC 821 and RFC 2822. Example usage:
 *
 * 

 * Mail m=new Mail("smtp.example.com");
 *
 * if(m.testConnection() == 0) {
 *     System.out.println("Connection to mailserver available");
 * } else {
 *     System.out.println("Problem with specified mailserver: "+m.getError());
 * }
 *
 * m.enableAuthentication("[email protected]","password");
 *  int result = m.sendMail("[email protected]","[email protected]","My subject","content2");
 * if(result>0) {
 *     System.err.println(m.getError());
 * }
 *
 * result=m.sendMail("[email protected]","[email protected]","Another subject","content2");
 * if(result>0) {
 *     System.err.println(m.getError());
 * }
 *
 * result=m.sendMails("[email protected]","[email protected],[email protected]","test1","content");
 * if(result>0) {
 *     System.err.println(m.getError());
 * }
 * 
*/ public class Mail { private String host = null; private int port = 25; private String error = ""; private static Random generator = new Random(); private int timeout = 10000; public Mail(String host, int port) { this.host = host; this.port = port; } public Mail(String host) { this.host = host; } String authUsername = null; String authPassword = null; boolean authEnabled = false; /** * Attempt to authenticate to the mail server, primarily used to enable * relaying of email where required. * * @param username Provide account username * @param password Specify account password */ public void enableAuthentication(String username, String password) { authUsername = username; authPassword = password; authEnabled = true; } /** * Disable attempting to authenticate with mail server. */ public void disableAuthentication() { authUsername = null; authPassword = null; authEnabled = false; } /** * Used to retrive the error message related generated due * to failure of sendMail() function. * * @return Text string containing english description of problem. */ public String getError() { String e2 = error; error = ""; return e2; } /** * Specify maximum length of time in milliseconds to wait for an SMTP server to respond. Default is ten seconds. * @param timeout Maximum wait time in milliseconds */ public void setTimeout(int timeout) { this.timeout = timeout; } /** * The maximum length of time to wait for an SMTP server to respond * @return Maximum wait time in milliseconds */ public int getTimeout() { return timeout; } /** * Send a message in plain text format, no html or mime encoding * * @param from Sender email address. * @param to Destination email address. * @param subject Subject of email message. * @param html content of email message to be sent, or null for no html. * @param text text content of the email * @param headers Extra header lines to insert, this may be null. * * @return 0 if successful, otherwise error number returned. */ public int send(String from, String to, String subject, String html, String text, List headers) { StringBuffer message = new StringBuffer(); Socket socket = null; String response = null; String datestamp = ""; Format dformat = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z"); datestamp = dformat.format(new Date()); Pattern p = Pattern.compile("[\"']*([^\"'<]*)[\"']* *<([^>]*)>"); String fromEmail = from; String fromName = ""; if(from.indexOf('<') > 0) { Matcher m = p.matcher(from); if(m.matches()) { fromName = m.group(1); fromEmail = m.group(2); } } String toEmail = to; String toName = ""; if(to.indexOf('<') > 0) { Matcher m = p.matcher(to); if(m.matches()) { toName = m.group(1); toEmail = m.group(2); } } EmailAddressParse etest = new EmailAddressParse(); if(!etest.isValid(fromEmail)) { error = etest.getError(); return 1; } if(!etest.isValid(toEmail)) { error = etest.getError(); return 1; } try { SocketAddress sockaddr = new InetSocketAddress(host, port); socket = new Socket(); socket.setSoTimeout(timeout); socket.connect(sockaddr, timeout); } catch(SocketTimeoutException e) { error = "Timeout while connecting to mail server"; if(socket != null) { try { socket.close(); } catch(IOException f) {} } return 2; } catch(IOException e) { error = "Unable to connect to mail server"; if(socket != null) { try { socket.close(); } catch(IOException f) {} } return 1; } try { InetAddress lina = InetAddress.getLocalHost(); OutputStream ps = socket.getOutputStream(); InputStreamReader dd = new InputStreamReader(socket.getInputStream()); BufferedReader dis = new BufferedReader(dd); response = dis.readLine(); if(response.indexOf("220 ") != 0) { error = "Mail did not respond like a mail server"; return 1; } message.append("HELO "); message.append(lina.toString()); message.append("\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response = dis.readLine(); if(response.indexOf("250 ") != 0) { error = response + " (Sent: " + message.toString() + ")"; return 1; } message.setLength(0); if(port == 587) { message.append("starttls\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response = dis.readLine(); if(response.indexOf("220 ") != 0) { error = "STARTTLS failed. " + response; return 1; } SSLSocket sslSocket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket( socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); dis = new BufferedReader(new InputStreamReader(sslSocket.getInputStream())); ps = sslSocket.getOutputStream(); message.setLength(0); } if(authEnabled) { message.append("AUTH LOGIN\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response = dis.readLine(); if(response.indexOf("334 ") != 0) { error = response; return 1; } message.setLength(0); message.append(Base64Encode.encode(authUsername)); message.append("\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response=dis.readLine(); if(response.indexOf("334 ") != 0) { error = response; return 1; } message.setLength(0); ps.write((Base64Encode.encode(authPassword) + "\r\n").getBytes()); ps.flush(); response = dis.readLine(); if(response.indexOf("235 ") != 0) { error = response; return 1; } } ps.write(("MAIL FROM:" + fromEmail + "\r\n").getBytes()); ps.flush(); response = dis.readLine(); if(response.indexOf("250 ") != 0) { error=response; return 1; } ps.write(("RCPT TO:" + toEmail + "\r\n").getBytes()); ps.flush(); response=dis.readLine(); if(response.indexOf("250 ") != 0) { error = response; return 1; } message.append("DATA\r\n"); ps.write(message.toString().getBytes()); response = dis.readLine(); if(response.indexOf("354 ") != 0) { error = response; return 1; } message.setLength(0); message.append("Date: "); message.append(datestamp); message.append("\r\n"); if(fromName.length() > 0) { message.append("From: \""); message.append(fromName); message.append("\" <"); message.append(fromEmail); message.append(">"); } else { message.append("From: "); message.append(fromEmail); } message.append("\r\n"); message.append("Subject: " + subject); message.append("\r\n"); if(toName.length() > 0) { message.append("To: \"" + toName + "\" <" + toEmail + ">"); message.append("\r\n"); } else { message.append("To: " + toEmail); message.append("\r\n"); } String messageId = null; if(headers != null) { for(String header : headers) { message.append(header); message.append("\r\n"); if(header.toLowerCase().startsWith("message-id:")) { messageId = header; } } } if(messageId == null) { message.append("Message-ID: <"+(new base.uuid.UUID().toString().toUpperCase())+"@"+lina.toString()+">"); message.append("\r\n"); } ps.write(message.toString().getBytes()); message.setLength(0); if(html != null && html.length() > 0) { Encoding quotedPrintable = new QuotedPrintableEncoding(); html = quotedPrintable.encode(html); Encoding plainText = new PlainTextEncoding(); text = plainText.encode(text); String boundary = String.valueOf(Math.abs(generator.nextLong())); message.append("Content-type: multipart/alternative; charset=UTF-8; boundary="); message.append(boundary); message.append("\r\n"); message.append("Mime-Version: 1.0\r\n"); message.append("\r\n"); message.append("--"); message.append(boundary); message.append("\r\n"); message.append("Content-Type: text/plain; charset=utf-8; format=flowed\r\n"); message.append("Content-Transfer-Encoding: 8bit\r\n"); message.append("Content-Disposition: inline\r\n"); message.append("\r\n"); message.append(text); message.append("\r\n\r\n"); message.append("--"); message.append(boundary); message.append("\r\n"); message.append("Content-Type: text/html; charset=utf-8\r\n"); message.append("Content-Transfer-Encoding: quoted-printable\r\n"); message.append("Content-Disposition: inline\r\n"); message.append("\r\n"); message.append(html); message.append("\r\n\r\n"); message.append("--"); message.append(boundary); message.append("--\r\n"); } else { message.append("\r\n"); Encoding plainText = new PlainTextEncoding(); text = plainText.encode(text); message.append(text); message.append("\r\n"); } message.append(".\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response = dis.readLine(); if(response == null) { error = "Error reading data from server. "; return 1; } if(response.indexOf("250 ") != 0) { error = response; return 1; } message.setLength(0); message.append("QUIT\r\n"); ps.write(message.toString().getBytes()); ps.flush(); response = dis.readLine(); if(response == null) { error = "Error reading data from server. "; return 1; } if(response.indexOf("221 ") != 0) { error = response; return 1; } message.setLength(0); } catch(SocketTimeoutException e) { error = "Timeout while waiting for response from mail server. " + StringHelper.exceptionToString(e, "\n"); if(message.length() > 0) { error = error + " (Sent: " + StringHelper.maxLength(message.toString(), 100) + ")"; } return 4; } catch (Exception ex) { error = "Problem communicating with mail server. " + StringHelper.exceptionToString(ex, "\n "); if(message.length() > 0) { error = error + " (Sent: " + StringHelper.maxLength(message.toString(), 100) + ")"; } return 2; } finally { if(socket != null) { try { socket.close(); } catch(IOException f) {} } } return 0; } /** * Used to test connection and communication with the specified mail server. * Will report if a connection can not be established with the mail server * or if the mailserver does not reply with content a mail server should reply * with, or finally if there are network difficulties at the time of the test. * * @return 0 if successful, >0 if not successful. Use getError() to read the problem. */ public int testConnection() { Socket socket = null; String response = null; try { SocketAddress sockaddr = new InetSocketAddress(host, port); socket = new Socket(); socket.setSoTimeout(timeout); socket.connect(sockaddr, timeout); } catch(SocketTimeoutException e) { error = "Timeout while connecting to mail server"; if(socket != null) { try { socket.close(); } catch(IOException f) {} } return 3; } catch(IOException e) { error = "Unable to connect to mail server"; if(socket != null) { try { socket.close(); } catch(IOException f) {} } return 1; } try { PrintStream ps = new PrintStream(socket.getOutputStream()); InputStreamReader dd = new InputStreamReader(socket.getInputStream()); BufferedReader dis = new BufferedReader(dd); response = dis.readLine(); if(response.indexOf("220 ") != 0) { error="Mail did not respond like a mail server"; return 1; } ps.println("QUIT"); ps.flush(); response = dis.readLine(); if(response.indexOf("221 ") != 0) { error = response; return 1; } } catch(SocketTimeoutException e) { error = "Timeout while waiting for response from mail server. " + StringHelper.exceptionToString(e, "\n"); try { socket.close(); } catch(IOException f) {} return 4; } catch (Exception e) { error = "Problem communicating with mail server. " + e.getMessage(); try { socket.close(); } catch(IOException f) {} return 2; } try { socket.close(); } catch(IOException e) {} return 0; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy