diff --git a/src/zutil/net/SMTPClient.java b/src/zutil/net/SMTPClient.java deleted file mode 100644 index 0206286..0000000 --- a/src/zutil/net/SMTPClient.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Ziver Koc - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * 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 OR COPYRIGHT HOLDERS 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 zutil.net; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Date; - -/** - * A simple class that connects and logs in to a SMTP - * server and then send emails. - * INFO: http://cr.yp.to/smtp/client.html - * - * @author Ziver - * - */ -public class SMTPClient { - public static boolean DEBUG = false; - - private BufferedReader in; - private PrintStream out; - private Socket socket; - private String url; - private int port; - - public SMTPClient(String url){ - this(url, 25); - } - - public SMTPClient(String url, int port){ - this.url = url; - this.port = port; - } - - /** - * Connects to the server. - * Sends the message. - * Closes the connection - * - * @param from The destination email address - * @param to The recipients email address - * @param subj The subject of the message - * @param msg The message - * @throws IOException - */ - public synchronized void send(String from, String to, String subj, String msg) throws IOException{ - try{ - connect(); - // FROM and TO - sendCommand("MAIL FROM:"+from); - sendCommand("RCPT TO:"+to); - sendCommand("DATA"); - // The Message - sendNoReplyCommand("Date: "+(new Date()), DEBUG); - sendNoReplyCommand("From: "+from, DEBUG); - sendNoReplyCommand("To: "+to, DEBUG); - sendNoReplyCommand("Subject: "+subj, DEBUG); - sendNoReplyCommand(" ", DEBUG); - sendNoReplyCommand(msg, DEBUG); - sendCommand(".", DEBUG); - - close(); - }catch(IOException e){ - close(); - throw e; - } - } - - /** - * Connects to the server - * - * @throws UnknownHostException - * @throws IOException - */ - public void connect() throws UnknownHostException, IOException{ - socket = new Socket(url, port); - in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - out = new PrintStream(socket.getOutputStream()); - - readCommand(DEBUG); - sendCommand("HELO "+url); - } - - /** - * Sends the given line to the server and returns a status integer - * - * @param cmd The command to send - * @return The return code from the server - * @throws IOException if the cmd fails - */ - private int sendCommand(String cmd) throws IOException{ - return parseReturnCode(sendCommand(cmd, DEBUG)); - } - - /** - * Sends the given line to the server and returns the last line - * - * @param cmd The command to send - * @param print To print out the received lines - * @return Last String line from the server - * @throws IOException - */ - private String sendCommand(String cmd, boolean print) throws IOException{ - sendNoReplyCommand(cmd, print); - return readCommand(print); - } - - /** - * Sends a given command and don't cares about the reply - * - * @param cmd The command - * @param print If it should print to System.out - * @throws IOException - */ - private void sendNoReplyCommand(String cmd, boolean print) throws IOException{ - out.println(cmd); - if(print)System.out.println(cmd); - } - - /** - * Reads on line from the command channel - * - * @param print If the method should print the input line - * @return The input line - * @throws IOException if the server returns a error code - */ - private String readCommand(boolean print) throws IOException{ - String tmp = in.readLine(); - if(print)System.out.println(tmp); - if(parseReturnCode(tmp) >= 400 ) throw new IOException(tmp); - - return tmp; - } - - /** - * Parses the return line from the server and returns the status code - * - * @param msg The message from the server - * @return The status code - * @throws IOException - */ - private synchronized int parseReturnCode(String msg){ - return Integer.parseInt(msg.substring(0, 3)); - } - - public void close() throws IOException{ - sendCommand("QUIT", DEBUG); - in.close(); - out.close(); - socket.close(); - } -} diff --git a/src/zutil/net/smtp/Email.java b/src/zutil/net/smtp/Email.java new file mode 100755 index 0000000..ced90be --- /dev/null +++ b/src/zutil/net/smtp/Email.java @@ -0,0 +1,99 @@ +package zutil.net.smtp; + +import java.io.IOException; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import sun.net.smtp.SmtpClient; + +/** + * Simplifies sending of a email + * + * @author Ziver + */ +public class Email { + public enum ContentType{ + PLAIN, HTML + } + private static final SimpleDateFormat dateFormatter = + new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); + + private String from; + private String niceFrom = null; + private String to; + private String replyTo = null; + private ContentType type = ContentType.PLAIN; + private String subject; + private String message; + + + + public Email(){ } + + + public void setFrom(String address){ + from = address; + } + public void setFrom(String address, String niceName){ + from = address; + niceFrom = niceName; + } + public String getFromAddress(){ + return from; + } + public void setReplyTo(String rpt){ + replyTo = rpt; + } + public void setTo(String t){ + to = t; + } + public String getTo(){ + return to; + } + public void setContentType(ContentType t){ + type = t; + } + public void setSubject(String s){ + subject = s; + } + public void setMessage(String msg){ + message = msg; + } + + + /** + * Will write the data from this object into a PrintStream. + * + * @throws IllegalArgumentException if from address and to address has not been set + */ + public void write(PrintStream out) throws IOException{ + if(from == null) + throw new IllegalArgumentException("From value cannot be null!"); + if(to == null) + throw new IllegalArgumentException("To value cannot be null!"); + + //************ Headers + if (niceFrom!=null) + out.println("From: \""+niceFrom+"\" <"+from+">"); + else + out.println("From: <"+from+">"); + if ( replyTo != null ) + out.println("Reply-To: <"+replyTo+">"); + out.println("To: " + to); + out.println("Subject: "+subject); + // Date + out.println("Date: "+dateFormatter.format(new Date(System.currentTimeMillis()))); + // Content type + switch( type ){ + case HTML: + out.println("Content-Type: text/html;"); break; + default: + out.println("Content-Type: text/plain;"); break; + } + out.println(); + + //*********** Mesasge + out.println( message ); + } +} \ No newline at end of file diff --git a/src/zutil/net/smtp/SMTPClient.java b/src/zutil/net/smtp/SMTPClient.java new file mode 100755 index 0000000..7dd9a82 --- /dev/null +++ b/src/zutil/net/smtp/SMTPClient.java @@ -0,0 +1,191 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 OR COPYRIGHT HOLDERS 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 zutil.net.smtp; + +import zutil.log.LogUtil; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A simple class that connects, authenticates and sends emails through a SMTP server + * + * @see SMTP Summary + * @see RFC2821 + * @author Ziver + * + */ +public class SMTPClient { + private static final Logger logger = LogUtil.getLogger(); + + private static final String NEWLINE = "\r\n"; + private static final String CMD_HELO = "HELO"; + private static final String CMD_FROM = "MAIL FROM"; + private static final String CMD_TO = "RCPT TO"; + private static final String CMD_DATA = "DATA"; + private static final String CMD_DATA_END = "."; + private static final String CMD_RESET = "RSET"; + private static final String CMD_NOOP = "NOOP"; + private static final String CMD_QUIT = "QUIT"; + + + private Socket socket; + private BufferedReader in; + private PrintStream out; + + + /** + * Will look for a SMTP server on localhost on port 25 + */ + public SMTPClient() throws IOException { + this("localhost", 25); + } + /** + * Will look for a SMTP server on specified host on port 25 + */ + public SMTPClient(String host) throws IOException { + this(host, 25); + } + public SMTPClient(String host, int port) throws IOException { + socket = new Socket(host, port); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new PrintStream(socket.getOutputStream()); + + readCommand(); + sendCommand(CMD_HELO + " " + InetAddress.getLocalHost().getHostName()); + } + + /** + * Sends a basic email to the smtp server + * + * @param from the senders email address + * @param to the recipients email address + * @param subj the email subject line + * @param msg the email body message + */ + public synchronized void send(String from, String to, String subj, String msg) throws IOException{ + if(from == null) + throw new IllegalArgumentException("From value cannot be null!"); + if(to == null) + throw new IllegalArgumentException("To value cannot be null!"); + try{ + // Pre metadata + sendCommand(CMD_FROM + ":" + from); + sendCommand(CMD_TO + ":" + to); + sendCommand(CMD_DATA); + // Message headers and body + out.println("From: "+from); + out.println("To: "+to); + out.println("Subject: "+subj); + out.println(""); + out.println(msg); + sendCommand(CMD_DATA_END); + reset(); + }catch(IOException e){ + logger.log(Level.SEVERE, null, e); + } + } + + /** + * Sends a email to the connected SMTP server + * + * @param email a email object containing message specific data + */ + public synchronized void send(Email email) throws IOException{ + if(email.getFromAddress() == null) + throw new IllegalArgumentException("From value cannot be null!"); + if(email.getTo() == null) + throw new IllegalArgumentException("To value cannot be null!"); + try{ + // Pre metadata + sendCommand(CMD_FROM + ":" + email.getFromAddress()); + sendCommand(CMD_TO + ":" + email.getTo()); + sendCommand(CMD_DATA); + // Message headers and body + email.write(out); + sendCommand(CMD_DATA_END); + reset(); + }catch(IOException e){ + logger.log(Level.SEVERE, null,e ); + } + } + + + + /** + * Sends the given line to the server and return the last line of the response + * + * @param cmd a String command that will be sent to the server + * @return the server response code + */ + public synchronized int sendCommand(String cmd) throws IOException{ + logger.finest(">> "+cmd); + out.print(cmd + NEWLINE); + String reply = readCommand(); + return parseReturnCode(reply); + } + + /** + * Reads on line from the command channel + * + * @throws IOException if the server returns a error code + */ + public synchronized String readCommand() throws IOException{ + String tmp = in.readLine(); + logger.finest(">> "+tmp); + if(parseReturnCode(tmp) >= 400 ) + throw new IOException(tmp); + + return tmp; + } + + private static int parseReturnCode(String msg){ + return Integer.parseInt(msg.substring(0, 3)); + } + + /** + * Reset the server context, this needs to be done + * between emails id multiple messages are sent + */ + public synchronized void reset() throws IOException { + sendCommand(CMD_RESET); + } + + public synchronized void close() throws IOException{ + if (in != null) { + sendCommand(CMD_QUIT); + socket.close(); + socket = null; + in = null; + out = null; + } + } +}