DM_DEFAULT_ENCODING: Be explicit that we're using 7-bit ASCII when sending email.
[cfb.git] / prod / net / jaekl / qd / util / SendMail.java
index 68befa72323fd6e8580cf3b77062bf51e99b388d..33be358b31edc0c28e7b232861e89419a76357ca 100644 (file)
@@ -3,10 +3,13 @@ package net.jaekl.qd.util;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -17,8 +20,17 @@ public class SendMail {
        private static final String RESP_251 = "251";   // mail address change (we don't support this)
        private static final String RESP_354 = "354";   // OK, proceed with DATA transmission
        
+       // Actually, RFC821 (with which all SMTP should be backwards-compatible)
+       // requires all control transmissions to be done in US-ASCII.
+       // However, there's no point in throwing an exception if the server with which 
+       // we're communicating sends bytes with the high bit set.  So, let's read from 
+       // the socket with the only Charset that Java guarantees will be available that 
+       // can also read arbitrary sequences of 8-bit bytes.
+       private static final String SMTP_CHARSET = "ISO-8859-1";
+       
        String m_hostName;
        String m_boundary;
+       Charset m_charset;
        
        String m_smtpHost;
        int m_smtpPort;
@@ -56,8 +68,8 @@ public class SendMail {
        {
                try (
                                Socket sock = openSocket(m_smtpHost, m_smtpPort);
-                               PrintWriter pw = new PrintWriter(sock.getOutputStream(), true);
-                               BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
+                               PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(), StandardCharsets.US_ASCII), true);
+                               BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream(), getCharset()));
                        ) 
                {
                        send(pw, br);
@@ -136,7 +148,7 @@ public class SendMail {
        void sendMimeHeaders(PrintWriter pw)
        {
                sendLine(pw, "MIME-Version: 1.0");
-               sendLine(pw, "Content-Type: multipart/mixed; boundary=" + getBoundary());
+               sendLine(pw, "Content-Type: multipart/mixed; boundary=\"" + getBoundary() + "\"");
        }
        
        void sendMimeParts(PrintWriter pw) {
@@ -159,6 +171,13 @@ public class SendMail {
                return true;
        }
        
+       Charset getCharset() {
+               if (null == m_charset) {
+                       m_charset = Charset.forName(SMTP_CHARSET);
+               }
+               return m_charset;
+       }
+       
        String getBoundary()
        {
                if (null != m_boundary) {