//
#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+#if MONO_X509_ALIAS
+extern alias PrebuiltSystem;
+#endif
-#if MONOTOUCH || MONODROID
-using System.Security.Cryptography.X509Certificates;
+#if MONO_SECURITY_ALIAS
+using MSI = MonoSecurity::Mono.Security.Interface;
#else
-extern alias PrebuiltSystem;
+using MSI = Mono.Security.Interface;
+#endif
+#if MONO_X509_ALIAS
using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-using System.Security.Cryptography.X509Certificates;
+#else
+using X509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
#endif
-
+using System.Security.Cryptography.X509Certificates;
#endif
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
-using System.Reflection;
using System.Net.Configuration;
using System.Configuration;
using System.Net.Security;
using System.Security.Authentication;
-#if NET_4_5
using System.Threading.Tasks;
-#endif
+using Mono.Net.Security;
namespace System.Net.Mail {
+ [Obsolete ("SmtpClient and its network of types are poorly designed, we strongly recommend you use https://github.com/jstedfast/MailKit and https://github.com/jstedfast/MimeKit instead")]
public class SmtpClient
-#if NET_4_0
: IDisposable
-#endif
{
#region Fields
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 : "");
}
#endif
-#if NET_4_0
public
-#endif
string TargetName { get; set; }
public ICredentialsByHost Credentials {
#endregion // Events
#region Methods
-#if NET_4_0
public void Dispose ()
{
Dispose (true);
{
// TODO: We should close all the connections and abort any async operations here
}
-#endif
private void CheckState ()
{
if (messageInProcess != null)
// FIXME: parse the list of extensions so we don't bother wasting
// our time trying commands if they aren't supported.
- status = SendCommand ("EHLO " + Dns.GetHostName ());
+
+ // Get the FQDN of the local machine
+ string fqdn = Dns.GetHostEntry (Dns.GetHostName ()).HostName;
+ status = SendCommand ("EHLO " + fqdn);
if (IsError (status)) {
- status = SendCommand ("HELO " + Dns.GetHostName ());
+ status = SendCommand ("HELO " + fqdn);
if (IsError (status))
throw new SmtpException (status.StatusCode, status.Description);
ResetExtensions();
writer = new StreamWriter (stream);
reader = new StreamReader (stream);
- status = SendCommand ("EHLO " + Dns.GetHostName ());
+ status = SendCommand ("EHLO " + fqdn);
if (IsError (status)) {
- status = SendCommand ("HELO " + Dns.GetHostName ());
+ status = SendCommand ("HELO " + fqdn);
if (IsError (status))
throw new SmtpException (status.StatusCode, status.Description);
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);
Send (new MailMessage (from, to, subject, body));
}
-#if NET_4_5
public Task SendMailAsync (MailMessage message)
{
var tcs = new TaskCompletionSource<object> ();
static void SendMailAsyncCompletedHandler (TaskCompletionSource<object> source, AsyncCompletedEventArgs e, SendCompletedEventHandler handler, SmtpClient client)
{
- if ((object) handler != e.UserState)
+ if (source != e.UserState)
return;
client.SendCompleted -= handler;
source.SetResult (null);
}
-#endif
private void SendDot()
{
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);
return "unknown";
}
-#if SECURITY_DEP
- RemoteCertificateValidationCallback callback = delegate (object sender,
- X509Certificate certificate,
- X509Chain chain,
- SslPolicyErrors sslPolicyErrors) {
- // honor any exciting callback defined on ServicePointManager
- if (ServicePointManager.ServerCertificateValidationCallback != null)
- return ServicePointManager.ServerCertificateValidationCallback (sender, certificate, chain, sslPolicyErrors);
- // otherwise provide our own
- if (sslPolicyErrors != SslPolicyErrors.None)
- throw new InvalidOperationException ("SSL authentication error: " + sslPolicyErrors);
- return true;
- };
-#endif
-
private void InitiateSecureConnection () {
SmtpResponse response = SendCommand ("STARTTLS");
throw new SmtpException (SmtpStatusCode.GeneralFailure, "Server does not support secure connections.");
}
-#if SECURITY_DEP
- SslStream sslStream = new SslStream (stream, false, callback, null);
+#if SECURITY_DEP
+ var tlsProvider = MonoTlsProviderFactory.GetProviderInternal ();
+ var settings = MSI.MonoTlsSettings.CopyDefaultSettings ();
+ settings.UseServicePointManagerCallback = true;
+ var sslStream = tlsProvider.CreateSslStream (stream, false, settings);
CheckCancellation ();
sslStream.AuthenticateAsClient (Host, this.ClientCertificates, SslProtocols.Default, false);
- stream = sslStream;
+ stream = sslStream.AuthenticatedStream;
#else
throw new SystemException ("You are using an incomplete System.dll build");