-1

I am trying to send email using a TCP connection in C# to an smtp server (google in this example). The response I am getting is that Authentication is required.

5.5.1 Authentication Required. Learn more at\n5.5.1 https://support.google.com/mail/?p=WantAuthError h66sm663716vke.21 - gsmtp

There is no authentication. I don't know the username and password of the account I am sending email TO.

All the other examples I have been able to find use a pre-build SMTP server and build a mail message.

I just want to be able to send email to ANY email account when someone needs to reset their password or I need to send a system message or whatever.

Here is my code:

TcpClient tcpclient = new TcpClient();
tcpclient.Connect("smtp.gmail.com", 465);

//not sure if I need port 465 or 587.
// implicit SSL is always used on SMTP port 465
System.Net.Security.SslStream sslstream = new System.Net.Security.SslStream(tcpclient.GetStream());
sslstream.AuthenticateAsClient("smtp.gmail.com");

writer = new StreamWriter(sslstream);
reader = new StreamReader(sslstream);

string replyText = string.Empty;
string[] capabilities = null;

// read the server's initial greeting
readResponse(220);

// identify myself and get the server's capabilities
if (sendCommand("EHLO myserver.com", ref replyText) == 250)
{
    // parse capabilities
        capabilities = replyText.Split(new Char[] { '\n' });
}
else
{
    // EHLO not supported, have to use HELO instead, but then
        // the server's capabilities are unknown...

    capabilities = new string[] { };

    sendCommand("HELO myserver.com", 250);
}

    // check for pipelining support... (OPTIONAL!!!)
        if (Array.IndexOf(capabilities, "PIPELINING") != -1)
        {
                // can pipeline...

                // send all commands first without reading responses in between
                writer.WriteLine("MAIL FROM:<" + "myserver@myserver.com" + ">");
                writer.WriteLine("RCPT TO:<" + "anyemail@gmail.com" + ">");
                writer.WriteLine("DATA");
                writer.Flush();

                // now read the responses...

                Exception e = null;

                // MAIL FROM
                int replyCode = readResponse(ref replyText);
                if (replyCode != 250)
                    e = new SmtpCmdFailedException(replyCode, replyText);

                // RCPT TO
                replyCode = readResponse(ref replyText);
                if ((replyCode != 250) && (replyCode != 251) && (e == null))
                    e = new SmtpCmdFailedException(replyCode, replyText);

                // DATA
                replyCode = readResponse(ref replyText);
                if (replyCode == 354)
                {
                    // DATA accepted, must send email followed by "."
                    writer.WriteLine("Subject: Email test");
                    writer.WriteLine("Test 1 2 3");
                    writer.WriteLine(".");
                    writer.Flush();

                    // read the response
                    replyCode = readResponse(ref replyText);
                    if ((replyCode != 250) && (e == null))
                        e = new SmtpCmdFailedException(replyCode, replyText);
                }
                else
                {
                    // DATA rejected, do not send email
                    if (e == null)
                        e = new SmtpCmdFailedException(replyCode, replyText);
                }

                if (e != null)
                {
                    // if any command failed, reset the session
                    sendCommand("RSET");
                    throw e;
                }
            }
            else
            {
                // not pipelining, MUST read each response before sending the next command...

                sendCommand("MAIL FROM:<" + "myserver@myserver.com" + ">", 250);
                try
                {
                    sendCommand("RCPT TO:<" + "anyemail@gmail.com" + ">", 250, 251);
                    sendCommand("DATA", 354);
                    writer.WriteLine("Subject: Email test");
                    writer.WriteLine("");
                    writer.WriteLine("Test 1 2 3");
                    writer.Flush();
                    sendCommand(".", 250);
                }
                catch (SmtpCmdFailedException e)
                {
                    // if any command failed, reset the session
                    sendCommand("RSET");
                    throw;
                }
            }

            // all done
            sendCommand("QUIT", 221);
Casey Crookston
  • 13,016
  • 24
  • 107
  • 193
  • Hi Rion. First, I'm sorry that someone downvoted you without an explanation. I think that's very rude. I voted you back up. That being said... this is a lot of code you have posted. It would help if you could at least show us the exact line where the error is happening. Did you click on the link in the error message? It looks like the info could be helpful. And last, I did a Google search for "C# send email through google account" and this was at the top of the results: https://stackoverflow.com/questions/32260/sending-email-in-net-through-gmail – Casey Crookston Nov 13 '19 at 15:26
  • (continuation of last comment)... 1) You are right that you don't need to (and can't) supply the password of the account you are sending TO. But you DO need to supply the password of the account you are sending FROM. 2) Your code is way overly complex. Sending an email from code is a really simple process that is very well documented. The question I linked to in the previous comment gives a *very* tight example. – Casey Crookston Nov 13 '19 at 15:32
  • (continuation of last comment)... 3) PLEASE be aware that you need to be VERY careful when sending emails via code. It's easy to get flagged as a spammer by Google. Even if you don't send out a lot of emails (which WILL get you flagged as a spammer) your emails are still likely to end up in the recipient's spam folder. Read up and know what you are getting yourself into. – Casey Crookston Nov 13 '19 at 15:33
  • Thanks Casey. I get the error message immediately after trying to send "MAIL FROM" command after the "EHLO" command if I don't authenticate first. You say I need to supply a password of the account I am sending from, but it is not a google account. It is a completely different email address from an external website. – Rion Carpadakis Nov 13 '19 at 15:54
  • Casey, The example link you sent above is trying to send email from one gmail account using gmail smtp server to another gmail account. I am trying to send from a completely external server from our work location. – Rion Carpadakis Nov 13 '19 at 16:00
  • Ok. So then I'm confused why you are trying to use Google at all? `tcpclient.Connect("smtp.gmail.com", 465);` – Casey Crookston Nov 13 '19 at 16:03
  • To be clear, the address you are trying to send TO doesn't matter. Your code will not (and should not) change if you are sending to somebody@gmail.com or somebody@yahoo.com or somebody@hotmail.com or somebody@anything.anything. Your code does not connect to the recipient's email server. That's the job of the email server you are sending from. Your code only connects to the server you are sening the email FROM. In other words, you need to connect to an email server and say, "I'd like you to send this email on my behalf. Here are my credentials. Please validate me and send this email." – Casey Crookston Nov 13 '19 at 16:10
  • I was trying to write code to send email TO an smtp server such as gmail or yahoo or Hotmail or anywhere as you said, but I am trying to do it through a TCP connection sending individual commands and getting the responses. Basically, my own personal smtp server but for sending only. In the sample code above, I am trying to send email TO a gmail account from my own private code. I am not trying to connect to another smtp server to send the email to someone at gmail. – Rion Carpadakis Nov 13 '19 at 16:25
  • I'm trying to manually connect to gmail and send the individual email commands through a tcp connection (EHLO, MAIL FROM, MAIL TO, QUIT), and process the responses (250, etc) myself. Once I send the "EHLO" or "HELO" and identify myself, google wants authentication before it will accept a "MAIL FROM" even though it is coming from a different email address that is NOT gmail. – Rion Carpadakis Nov 13 '19 at 16:25
  • I have seen other c# mail servers out there such as lumisoft, etc. I was just trying to write a simple smtp server that wasn't as complex as that which would allow us to send out emails from our company without having to connect to our hosting provider smtp server. – Rion Carpadakis Nov 13 '19 at 16:27
  • When a shared hosting provider is used, the ip address from emails is often blocked as spam because the provider has hundreds of websites from different customers, many who have sent out so many emails that the ip address is now blocked. with a static address on our site alone, I can avoid this as it has never been used for spamming. our company emails will more likely be accepted. – Rion Carpadakis Nov 13 '19 at 16:28
  • Ah, ok! Now I understand Well, in that case, I am going to respectfully bow out. I truly can't help you... because I don't know how! But I will say this: What little bit I know is that the rules that govern the sending of emails are mighty complex, and it's really easy (if you do it wrong) to get blacklisted as a spammer. I wish you the best of luck. – Casey Crookston Nov 13 '19 at 16:29
  • No problem. Thanks for the help – Rion Carpadakis Nov 13 '19 at 16:37

1 Answers1

0

You will need a DNS library that allows you to lookup the MX records of the recipient's domain and then connect to that SMTP server address.

Read more here: https://serverfault.com/questions/392770/smtp-session-between-2-mail-servers-on-the-internet-without-authentication

jstedfast
  • 35,744
  • 5
  • 97
  • 110