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

base.email.Mail Maven / Gradle / Ivy

Go to download

A collection of basic java utility classes that provide basic features for a standalone/simple JEE application. Backed by a Cassandra, MySQL, or SQLite database, it provides, web page templates, user and group management, and a searchable online audit log of all user activity.

There is a newer version: 1.5.4
Show newest version
/*
 This is free and unencumbered software released into the public domain.

 Anyone is free to copy, modify, publish, use, compile, sell, or
 distribute this software, either in source code form or as a compiled
 binary, for any purpose, commercial or non-commercial, and by any
 means.

 In jurisdictions that recognize copyright laws, the author or authors
 of this software dedicate any and all copyright interest in the
 software to the public domain. We make this dedication for the benefit
 of the public at large and to the detriment of our heirs and
 successors. We intend this dedication to be an overt act of
 relinquishment in perpetuity of all present and future rights to this
 software under copyright law.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
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