Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
905 views
in Technique[技术] by (71.8m points)

c# - Send SMTP mail from Gmail, live, aol or yahoo accounts when my PC is connected via proxy or without proxy to internet

I want to send email in C# via SMTP to different mail providers example Gmail, Yahoo, AOL, Msn, Live etc so that my code works fine if my computer is connected to internet via proxy or connected directly to internet. (Proxy is a forward proxy taking requests from an internal network and forwarding them to the Internet and I configure proxy in I.E. as)
.................................

I have code by which I can send SMTP mail if PC is not connected via proxy

    public void SendMail(string senderId, string password, List<string> To, List<string> CC, List<string> BCC, string Subject, string Body, List<Attachment> Attachment)
    {
        SmtpClient SmtpServer = null;
        string[] ss = senderId.Split('@');

        string ServerName = ss[1].Substring(0, ss[1].IndexOf("."));

        switch (ServerName.ToLower())
        {
            case "gmail":
                SmtpServer = new SmtpClient("smtp.gmail.com");
                SmtpServer.Port = 587;
                SmtpServer.Credentials = new System.Net.NetworkCredential(senderId, password);
                SmtpServer.EnableSsl = true;
                break;
            case "msn":
            case "live":
            case "hotmail":
            case "outlook":
                SmtpServer = new SmtpClient("smtp.live.com");
                SmtpServer.Port = 25;
                SmtpServer.Credentials = new System.Net.NetworkCredential(senderId, password);
                SmtpServer.EnableSsl = true;
                break;

            case "aol":
                SmtpServer = new SmtpClient("smtp.aol.com");
                SmtpServer.Port = 25;
                SmtpServer.Credentials = new System.Net.NetworkCredential(senderId, password);
                SmtpServer.EnableSsl = true;
                break;
            case "yahoo":
            case "ymail":
            case "rocketmail":
            case "yahoomail":
                SmtpServer = new SmtpClient("smtp.mail.yahoo.com");
                SmtpServer.Port = 25;
                SmtpServer.Credentials = new System.Net.NetworkCredential(senderId, password);
                SmtpServer.EnableSsl = false;
                break;
            default:

                break;


        }
        SmtpServer.DeliveryMethod = SmtpDeliveryMethod.Network;

        MailMessage mail = new MailMessage();
        mail.From = new MailAddress(senderId);

        foreach (string item in To)
        {
            mail.To.Add(item);
        }
        foreach (string item in CC)
        {
            mail.CC.Add(item);
        }
        foreach (string item in BCC)
        {
            mail.Bcc.Add(item);
        }

        mail.Subject = Subject;
        mail.Body = Body;

        foreach (Attachment item in Attachment)
        {
            mail.Attachments.Add(item);
        }

        SmtpServer.Send(mail);

    }

This is working perfectly fine but I want to send email when I am connected via proxy.

I have read so many posts like, Sending Mail over proxy server
ASP.net SMTP Mail though Proxy
Is there .NET library for email sending via PROXY?
They all state it is not possible but while searching I found chilkat library, limilabs sample which allows user to send mail via proxies by configuring the proxy.
I have researched a lot, I have read SOCKS proxy, learnt how to send SMTP mail using raw sockets but I am unable to find solution something missing.
I will appreciate any ideas for some work that has been done before, if any one who faced the same problem or any ideas what I can do?

EDIT:- As I have already mentioned that, I have found samples using Chilkat and limilabs it means I do not want to use those and I am not allowed to use any third party dll

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Sending mails via proxy server was a little tricky but at the end solved the problem by using the code to send mails via socket.

Late at posting answer but lets assume it might be helpful to others.

Took help from code at link

Attaching the code below, the SmtpServer object is same as described in question,

   #region ..... SOCKET MAIL .....

    private enum SMTPResponse : int
    {
        /// <summary>
        /// 220
        /// </summary>
        CONNECT_SUCCESS = 220,
        /// <summary>
        /// 235
        /// </summary>
        CRED_SUCCESS = 235,
        /// <summary>
        /// 250
        /// </summary>
        GENERIC_SUCCESS = 250,
        /// <summary>
        /// 334
        /// </summary>
        AUTH_SUCCESS = 334,
        /// <summary>
        /// 354
        /// </summary>
        DATA_SUCCESS = 354,
        /// <summary>
        /// 221
        /// </summary>
        QUIT_SUCCESS = 221
    }

    public static string EncodeTo64(string toEncode)
    {

        byte[] toEncodeAsBytes = System.Text.Encoding.ASCII.GetBytes(toEncode);

        string returnValue = System.Convert.ToBase64String(toEncodeAsBytes, Base64FormattingOptions.None);

        return returnValue;

    }

    public bool SendFromSocket(MailMessage message)
    {
        var requestUri = new System.Uri("smtps://" +SmtpServer.Host +":"+SmtpServer.Port);

        Uri proxy = null;
        //This is magic code which does your job for the proxy 
        using (var web = new System.Net.WebClient())
        {                
            proxy = web.Proxy.GetProxy(requestUri);                
        }

        using (var s = new TcpClient(proxy.DnsSafeHost, proxy.Port  ))
        {               
            using (var stream = s.GetStream())
            using (var clearTextReader = new StreamReader(stream))
            using (var clearTextWriter = new StreamWriter(stream) { AutoFlush = true })
            using (var sslStream = new SslStream(stream))
            {
                if (!Check_Response(clearTextReader, SMTPResponse.CONNECT_SUCCESS))
                {
                    s.Close();
                    return false;
                }

                clearTextWriter.WriteLine("HELO");
                if (!Check_Response(clearTextReader, SMTPResponse.GENERIC_SUCCESS))
                {
                    s.Close();
                    return false;
                }

                clearTextWriter.WriteLine("STARTTLS");
                if (!Check_Response(clearTextReader, SMTPResponse.CONNECT_SUCCESS))
                {
                    s.Close();
                    return false;
                }


                sslStream.AuthenticateAsClient(SmtpServer.Host);
                bool flag = sslStream.IsAuthenticated;

                using (var reader = new StreamReader(sslStream))
                using (var writer = new StreamWriter(sslStream) { AutoFlush = true })
                {                       
                    writer.WriteLine(string.Format("EHLO {0}", SmtpServer.Host));
                    if (!Check_Response(reader, SMTPResponse.GENERIC_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }

                    writer.WriteLine("AUTH LOGIN");
                    if (!Check_Response(reader, SMTPResponse.AUTH_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }

                    writer.WriteLine(EncodeTo64(SenderId));
                    if (!Check_Response(reader, SMTPResponse.AUTH_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }

                    writer.WriteLine(EncodeTo64(Password));
                    if (!Check_Response(reader, SMTPResponse.CRED_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }

                    writer.WriteLine("MAIL FROM: <{0}>", message.From);
                    if (!Check_Response(reader, SMTPResponse.GENERIC_SUCCESS))
                    {

                        s.Close();
                        return false;
                    }

                    foreach (MailAddress To in message.To)
                    {
                        writer.WriteLine("RCPT TO: <{0}>", To.Address);
                        if (!Check_Response(reader, SMTPResponse.GENERIC_SUCCESS))
                        {
                            s.Close();
                            return false;
                        }
                    }

                    if (message.CC != null)
                    {
                        foreach (MailAddress cc in message.CC)
                        {
                            writer.WriteLine(string.Format("RCPT TO: <{0}>", cc.Address));
                            if (!Check_Response(reader, SMTPResponse.GENERIC_SUCCESS))
                            {
                                s.Close();
                                return false;
                            }
                        }
                    }

                    StringBuilder Header = new StringBuilder();
                    Header.Append("From: " + message.From + "
");
                    Header.Append("To: ");
                    for (int i = 0; i < message.To.Count; i++)
                    {
                        Header.Append(i > 0 ? "," : "");
                        Header.Append(message.To[i].Address);
                    }
                    Header.Append("
");
                    if (message.CC != null)
                    {
                        Header.Append("Cc: ");
                        for (int i = 0; i < message.CC.Count; i++)
                        {
                            Header.Append(i > 0 ? "," : "");
                            Header.Append(message.CC[i].Address);
                        }
                        Header.Append("
");
                    }
                    Header.Append("Date: ");
                    Header.Append(DateTime.Now.ToString("ddd, d M y H:m:s z"));
                    Header.Append("
");
                    Header.Append("Subject: " + message.Subject + "
");
                    Header.Append("X-Mailer: SMTPDirect v1
");
                    string MsgBody = message.Body;
                    if (!MsgBody.EndsWith("
"))
                        MsgBody += "
";
                    if (message.Attachments.Count > 0)
                    {
                        Header.Append("MIME-Version: 1.0
");
                        Header.Append("Content-Type: multipart/mixed; boundary=unique-boundary-1
");
                        Header.Append("
");
                        Header.Append("This is a multi-part message in MIME format.
");
                        StringBuilder sb = new StringBuilder();
                        sb.Append("--unique-boundary-1
");
                        sb.Append("Content-Type: text/plain
");
                        sb.Append("Content-Transfer-Encoding: 7Bit
");
                        sb.Append("
");
                        sb.Append(MsgBody + "
");
                        sb.Append("
");

                        foreach (object o in message.Attachments)
                        {
                            Attachment a = o as Attachment;
                            byte[] binaryData;
                            if (a != null)
                            {
                                //FileInfo f = new FileInfo(a.);
                                sb.Append("--unique-boundary-1
");
                                sb.Append("Content-Type: application/octet-stream; file=" + a.Name + "
");
                                sb.Append("Content-Transfer-Encoding: base64
");
                                sb.Append("Content-Disposition: attachment; filename=" + a.Name + "
");
                                sb.Append("
");
                                Stream fs = a.ContentStream;
                                binaryData = new Byte[fs.Length];
                                long bytesRead = fs.Read(binaryData, 0, (int)fs.Length);
                                fs.Close();
                                string base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length);

                                for (int i = 0; i < base64String.Length; )
                                {
                                    int nextchunk = 100;
                                    if (base64String.Length - (i + nextchunk) < 0)
                                        nextchunk = base64String.Length - i;
                                    sb.Append(base64String.Substring(i, nextchunk));
                                    sb.Append("
");
                                    i += nextchunk;
                                }
                                sb.Append("
");
                            }
                        }
                        MsgBody = sb.ToString();
                    }

                    writer.WriteLine("DATA
");
                    if (!Check_Response(reader, SMTPResponse.DATA_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }
                    Header.Append("
");
                    Header.Append(MsgBody);
                    Header.Append(".
");
                    Header.Append("
");
                    Header.Append("
");
                    writer.WriteLine(Header.ToString());
                    if (!Check_Response(reader, SMTPResponse.GENERIC_SUCCESS))
                    {
                        s.Close();
                        return false;
                    }

                    writer.WriteLine("QUIT
");
                    Check_Response(reader, SMTPResponse.QUIT_SUCCESS);
                    s.Close();
                    return true;
                }
            }

        }
    }

    private static bool Check_Response(StreamReader netStream, SMTPResponse response_expected)
    {

        int response;

        int read = 0;

        StringBuilder sResponse = new StringBuilder();
        do
        {
            char[] buffer = new char[1024];                
            read = netStream.Read(buffer, 0, buffer.Length);
            sResponse.Append(buffer);                
        }
        while (read == 1024);

        response = Convert.ToInt32(sResponse.ToString().Substring(0, 3));

        if (response != (int)response_expected)
            return false;
        return true;
    }

    #endregion ..... SOCKET MAIL .....

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...