// SmtpSendAtt.java - a sample to send email with a text attachment to an SMTP server // by Rowland http://home.comcast.net/~rowland3 import java.io.*; import java.net.*; import java.text.DateFormat; import java.util.*; class MailMessage { String subject; String date; Vector vbodylines; // of String. message text is a vector of strings public final String sender, recipient; TreeMap header= new TreeMap(); public MailMessage(String _sender, String _recipient) { sender= _sender; recipient= _recipient; vbodylines = new Vector(); } public void addHeaderLine(String line) { try { int ix= line.indexOf(": "); if (ix< 0) return; String key= line.substring(0, ix); String val= line.substring(ix+2); if (val.endsWith("\n")) val= val.substring(val.length()-1); // get rid of trailing LF if (val.endsWith("\r")) val= val.substring(val.length()-1); // get rid of trailing CRLF header.put(key, val); } catch (Exception E) { System.err.println("MailMessage.addheaderLine: "+ line); } } public void addHeaderVal(String key, String val) { header.put(key, val); } public void addMailMessageLine(String _line) { vbodylines.add(_line); } public Enumeration getMailMessageLines() { return vbodylines.elements(); } public Iterator getHeaderFields() { return header.keySet().iterator(); } public String getHeaderVal(String key) { Object O= header.get(key); if (O== null) return null; return (String)O; } public String senderUname() { int ix= sender.indexOf("@"); if (ix< 0) return sender; return sender.substring(0, ix); } public String toString() { String s= "Sender: "+ sender+ "\tRecipient: "+ recipient+ "\n"; Iterator hi= header.keySet().iterator(); while (hi.hasNext()) { String key= (String)hi.next(); String hline= key+ ": "+ header.get(key)+ "\n"; s+= hline; } s+= "\n"; Enumeration e= vbodylines.elements(); while (e.hasMoreElements()) { s+= (String)e.nextElement()+ "\n"; } return s; } } //------------------------------------------------------------------------------ class SmtpSender { Socket sserver; BufferedReader in; OutputStreamWriter out; static final int SMTP_PORT= 25; SmtpSender(MailMessage message, String server) { try { sserver= new Socket(server, SMTP_PORT); send(message, sserver); sserver.close(); } catch (Exception E) { System.err.println("SmtpSender.SmtpSender: "+ E.toString()+ " "+ E.getMessage()); } } protected void send(MailMessage message, Socket sserver) { try { // A bit convoluted, but doesn't depend on DNS in any way... InetAddress localhost= sserver.getLocalAddress(); String localaddress= localhost.getHostAddress(); // Mandatory header fields, Date and From if (message.getHeaderVal("Date")== null) message.addHeaderVal("Date", new java.util.Date().toString()); if (message.getHeaderVal("From")== null) message.addHeaderVal("From", message.senderUname()+ " <"+ message.sender+ ">"); out= new OutputStreamWriter(sserver.getOutputStream()); in = new BufferedReader(new InputStreamReader(sserver.getInputStream())); String sintro= readln(); if (!sintro.startsWith("220")) { // 220 System.err.println("SmtpSender: intro=="+ sintro); return; } writeln("EHLO "+ localaddress); if (!expect250()) return; String sender= message.sender; int ix= sender.indexOf("@"); if (ix< 0) { // fill in sender domain sender+= "@"+ localaddress; } writeln("MAIL FROM:<"+ sender+ ">"); if (!expect250()) return; writeln("RCPT TO:<"+ message.recipient+ ">"); if (!expect250()) return; writeln("DATA"); while (true) { // may be multiple 250 replies pending from server String line= readln(); if (line.startsWith("3")) break; // ready to send if (!line.startsWith("2")) { System.err.println("SmtpSender.send reponse to DATA: "+ line); return; } } Iterator hi= message.getHeaderFields(); while (hi.hasNext()) { String key= (String)hi.next(); writeln(key+ ": "+ message.getHeaderVal(key)); } writeln(""); // end of header; Enumeration e= message.getMailMessageLines(); while (e.hasMoreElements()) { String bline= (String)e.nextElement(); if (bline.startsWith(".")) bline= "."+ bline; writeln(bline); } writeln("."); expect250(); writeln("QUIT"); } catch (Exception E) { System.err.println("SmtpSender.send: "+ E.toString()); } } final boolean expect250() throws IOException { String line= readln(); if (!line.startsWith("2")) { System.err.println("SmtpSender.expect250: "+ line); return false; } return true; } final void writeln(String s) throws IOException { System.err.println("From client: "+ s); out.write(s+ "\r\n"); out.flush(); } final String readln() throws IOException { String line= in.readLine(); System.err.println("From server: "+ line); return line; } protected static Socket serverConnect(String server) { Socket ss= null; try { ss= new Socket(server, SMTP_PORT); } catch (Exception E) { ss= null; } return ss; } protected static String serverConnectTest(String server) { Socket ss= serverConnect(server); if (ss== null) return null; try { ss.close(); } catch (Exception E) { } return server; } public static String suitableServer(String domain) { String server; server= serverConnectTest("smtp."+ domain); if (server== null) server= serverConnectTest("mail."+ domain); if (server== null) server= serverConnectTest(domain); return server; } public static void main(String args[]) { // usage: java SmtpSender mailaddress [smtpserver] String mailaddress= args[0]; MailMessage message= new MailMessage("SmtpSender", mailaddress); message.addHeaderVal("Subject", "SmtpSender test"); message.addMailMessageLine("SmtpSender test body"); if (args.length> 1) { new SmtpSender(message, args[1]); } else { // try to pick a suitable SMTP server int ix= mailaddress.indexOf("@"); if (ix< 0) { System.err.println("No server, can't get domain from email address."); return; } String domain= mailaddress.substring(ix+1); String smtpserver= suitableServer(domain); if (smtpserver== null) { System.err.println("Can't find an SMTP server for domain "+ domain); return; } new SmtpSender(message, smtpserver); } } } //------------------------------------------------------------------------------ // An email message with text attachments. class MailMessageAtt { public final String sender, recipient; protected Vector vbodylines; // of String. the main body of the message, as distinct from attachments protected TreeMap attachments; // key is filename, value is file content. protected MailMessage message= null; TreeMap header= new TreeMap(); public MailMessageAtt(String _sender, String _recipient) { sender= _sender; recipient= _recipient; vbodylines= new Vector(); attachments= new TreeMap(); } public void addHeaderVal(String key, String val) { header.put(key, val); } public void addMailMessageLine(String _line) { vbodylines.add(_line); } // an override of super public void addAttachment(String filename, String contents) { attachments.put(filename, contents); } /** buildBody prepares the message for sending **/ public MailMessage buildBody() { message= new MailMessage(sender, recipient); Iterator ih= header.keySet().iterator(); while (ih.hasNext()) { String key= (String)ih.next(); message.addHeaderVal(key, (String)header.get(key)); } String boundary= "=-nKLNP4OUaGthYYglpjig"; message.addHeaderVal("Content-Type", "multipart/mixed; boundary=\""+ boundary+ "\""); // the main body: message.addMailMessageLine(""); message.addMailMessageLine("--"+ boundary); message.addMailMessageLine("Content-Type: text/plain"); message.addMailMessageLine("Content-Transfer-Encoding: 7bit"); message.addMailMessageLine(""); Enumeration e= vbodylines.elements(); while (e.hasMoreElements()) { String line= (String)e.nextElement(); message.addMailMessageLine(line); } // the attachments: Iterator ai= attachments.keySet().iterator(); while(ai.hasNext()) { String filename= (String)ai.next(); message.addMailMessageLine("--"+ boundary); message.addMailMessageLine("Content-Disposition: attachment; filename="+ filename); message.addMailMessageLine("Content-Transfer-Encoding: quoted-printable"); message.addMailMessageLine("Content-Type: text/plain; charset=ANSI_X3.4-1968"); message.addMailMessageLine(""); String abody= (String)attachments.get(filename); while (true) { int ix= abody.indexOf("\n"); if (ix< 0) { message.addMailMessageLine(abody); break; } String line= abody.substring(0, ix); abody= abody.substring(ix+1); if (line.endsWith("\r")) line= line.substring(0, ix-1); message.addMailMessageLine(line); } } return message; } public String toString() { return buildBody().toString(); } } //------------------------------------------------------------------------------ public class SmtpSendAtt { public static void main(String args[]) { // usage: java SmtpSendAtt mailaddress [smtpserver] String mailaddress= args[0]; MailMessageAtt messatt= new MailMessageAtt("SmtpSendAtt", mailaddress); messatt.addHeaderVal("Subject", "SmtpSendAtt test"); messatt.addMailMessageLine("SmtpSendAtt test body"); messatt.addAttachment("attachment.txt", "Attachment contents"); MailMessage message= messatt.buildBody(); if (args.length> 1) { new SmtpSender(message, args[1]); } else { // try to pick a suitable SMTP server int ix= mailaddress.indexOf("@"); if (ix< 0) { System.err.println("No server, can't get domain from email address."); return; } String domain= mailaddress.substring(ix+1); String smtpserver= SmtpSender.suitableServer(domain); if (smtpserver== null) { System.err.println("Can't find an SMTP server for domain "+ domain); return; } new SmtpSender(message, smtpserver); } } }