Fix dot stuffing in SmtpClient
[mono.git] / mcs / class / System / System.Net.Mail / SmtpClient.cs
index 5b496e14ce55587de1c814557d30cfd9afce411c..ab1bde4ff7fd86789d37c22aa278abeb7f8cd0c1 100644 (file)
 
 #if SECURITY_DEP
 
-#if MONOTOUCH
+#if MONOTOUCH || MONODROID
 using System.Security.Cryptography.X509Certificates;
 #else
 extern alias PrebuiltSystem;
 using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
+using System.Security.Cryptography.X509Certificates;
 #endif
 
 #endif
@@ -47,7 +48,6 @@ using System.IO;
 using System.Net;
 using System.Net.Mime;
 using System.Net.Sockets;
-using System.Security.Cryptography.X509Certificates;
 using System.Text;
 using System.Threading;
 using System.Reflection;
@@ -55,12 +55,11 @@ using System.Net.Configuration;
 using System.Configuration;
 using System.Net.Security;
 using System.Security.Authentication;
+using System.Threading.Tasks;
 
 namespace System.Net.Mail {
        public class SmtpClient
-#if NET_4_0
        : IDisposable
-#endif
        {
                #region Fields
 
@@ -122,9 +121,7 @@ namespace System.Net.Mail {
                        if (cfg != null) {
                                this.host = cfg.Network.Host;
                                this.port = cfg.Network.Port;
-#if NET_4_0
                                this.enableSsl = cfg.Network.EnableSsl;
-#endif
                                TargetName = cfg.Network.TargetName;
                                if (this.TargetName == null)
                                        TargetName = "SMTPSVC/" + (host != null ? host : "");
@@ -171,9 +168,7 @@ namespace System.Net.Mail {
                }
 #endif
 
-#if NET_4_0
                public
-#endif
                string TargetName { get; set; }
 
                public ICredentialsByHost Credentials {
@@ -261,7 +256,6 @@ namespace System.Net.Mail {
                #endregion // Events 
 
                #region Methods
-#if NET_4_0
                public void Dispose ()
                {
                        Dispose (true);
@@ -272,7 +266,6 @@ namespace System.Net.Mail {
                {
                        // TODO: We should close all the connections and abort any async operations here
                }
-#endif
                private void CheckState ()
                {
                        if (messageInProcess != null)
@@ -547,8 +540,12 @@ namespace System.Net.Mail {
                                MailAddress from = message.From;
                                if (from == null)
                                        from = defaultFrom;
-                               
-                               SendHeader (HeaderName.Date, DateTime.Now.ToString ("ddd, dd MMM yyyy HH':'mm':'ss zzz", DateTimeFormatInfo.InvariantInfo));
+
+                               string dt = DateTime.Now.ToString("ddd, dd MMM yyyy HH':'mm':'ss zzz", DateTimeFormatInfo.InvariantInfo);
+                               // remove ':' from time zone offset (e.g. from "+01:00")
+                               dt = dt.Remove(dt.Length - 3, 1);
+                               SendHeader(HeaderName.Date, dt);
+
                                SendHeader (HeaderName.From, EncodeAddress(from));
                                SendHeader (HeaderName.To, EncodeAddresses(message.To));
                                if (message.CC.Count > 0)
@@ -654,16 +651,8 @@ namespace System.Net.Mail {
                                        sfre.Add (new SmtpFailedRecipientException (status.StatusCode, message.Bcc [i].Address));
                        }
 
-#if TARGET_JVM // List<T>.ToArray () is not supported
-                       if (sfre.Count > 0) {
-                               SmtpFailedRecipientException[] xs = new SmtpFailedRecipientException[sfre.Count];
-                               sfre.CopyTo (xs);
-                               throw new SmtpFailedRecipientsException ("failed recipients", xs);
-                       }
-#else
                        if (sfre.Count >0)
                                throw new SmtpFailedRecipientsException ("failed recipients", sfre.ToArray ());
-#endif
 
                        // DATA
                        status = SendCommand ("DATA");
@@ -707,13 +696,8 @@ namespace System.Net.Mail {
                        if (message.ReplyToList.Count > 0)
                                SendHeader ("Reply-To", EncodeAddresses (message.ReplyToList));
 
-#if NET_4_0
                        foreach (string s in message.Headers.AllKeys)
                                SendHeader (s, ContentType.EncodeSubjectRFC2047 (message.Headers [s], message.HeadersEncoding));
-#else
-                       foreach (string s in message.Headers.AllKeys)
-                               SendHeader (s, message.Headers [s]);
-#endif
        
                        AddPriorityHeader (message);
 
@@ -741,6 +725,41 @@ namespace System.Net.Mail {
                        Send (new MailMessage (from, to, subject, body));
                }
 
+               public Task SendMailAsync (MailMessage message)
+               {
+                       var tcs = new TaskCompletionSource<object> ();
+                       SendCompletedEventHandler handler = null;
+                       handler = (s, e) => SendMailAsyncCompletedHandler (tcs, e, handler, this);
+                       SendCompleted += handler;
+                       SendAsync (message, tcs);
+                       return tcs.Task;
+               }
+
+               public Task SendMailAsync (string from, string recipients, string subject, string body)
+               {
+                       return SendMailAsync (new MailMessage (from, recipients, subject, body));
+               }
+
+               static void SendMailAsyncCompletedHandler (TaskCompletionSource<object> source, AsyncCompletedEventArgs e, SendCompletedEventHandler handler, SmtpClient client)
+               {
+                       if ((object) handler != e.UserState)
+                               return;
+
+                       client.SendCompleted -= handler;
+
+                       if (e.Error != null) {
+                               source.SetException (e.Error);
+                               return;
+                       }
+
+                       if (e.Cancelled) {
+                               source.SetCanceled ();
+                               return;
+                       }
+
+                       source.SetResult (null);
+               }
+
                private void SendDot()
                {
                        writer.Write(".\r\n");
@@ -762,13 +781,8 @@ namespace System.Net.Mail {
                                CheckCancellation ();
 
                                if (escapeDots) {
-                                       int i;
-                                       for (i = 0; i < line.Length; i++) {
-                                               if (line[i] != '.')
-                                                       break;
-                                       }
-                                       if (i > 0 && i == line.Length) {
-                                               line += ".";
+                                       if (line.Length > 0 && line[0] == '.') {
+                                               line = "." + line;
                                        }
                                }
                                writer.Write (line);
@@ -934,11 +948,7 @@ try {
                                case TransferEncoding.Base64:
                                        byte [] content = new byte [av.ContentStream.Length];
                                        av.ContentStream.Read (content, 0, content.Length);
-#if TARGET_JVM
-                                       SendData (Convert.ToBase64String (content));
-#else
                                            SendData (Convert.ToBase64String (content, Base64FormattingOptions.InsertLineBreaks));
-#endif
                                        break;
                                case TransferEncoding.QuotedPrintable:
                                        byte [] bytes = new byte [av.ContentStream.Length];
@@ -978,11 +988,7 @@ try {
                                case TransferEncoding.Base64:
                                        byte [] content = new byte [lr.ContentStream.Length];
                                        lr.ContentStream.Read (content, 0, content.Length);
-#if TARGET_JVM
-                                       SendData (Convert.ToBase64String (content));
-#else
                                            SendData (Convert.ToBase64String (content, Base64FormattingOptions.InsertLineBreaks));
-#endif
                                        break;
                                case TransferEncoding.QuotedPrintable:
                                        byte [] bytes = new byte [lr.ContentStream.Length];
@@ -1014,11 +1020,7 @@ try {
                                att.ContentStream.Read (content, 0, content.Length);
                                switch (att.TransferEncoding) {
                                case TransferEncoding.Base64:
-#if TARGET_JVM
-                                       SendData (Convert.ToBase64String (content));
-#else
                                        SendData (Convert.ToBase64String (content, Base64FormattingOptions.InsertLineBreaks));
-#endif
                                        break;
                                case TransferEncoding.QuotedPrintable:
                                        SendData (ToQuotedPrintable (content));
@@ -1154,9 +1156,7 @@ try {
                                throw new SmtpException (SmtpStatusCode.GeneralFailure, "Server does not support secure connections.");
                        }
 
-#if TARGET_JVM
-                       ((NetworkStream) stream).ChangeToSSLSocket ();
-#elif SECURITY_DEP
+#if   SECURITY_DEP
                        SslStream sslStream = new SslStream (stream, false, callback, null);
                        CheckCancellation ();
                        sslStream.AuthenticateAsClient (Host, this.ClientCertificates, SslProtocols.Default, false);