Search code examples
powershellemailauthenticationsmtpclient

Why won't SmtpClient authenticate in my powershell script?


I'm trying to send an email from a PowerShell script, but I cannot seem to get it to properly authenticate with my SMTP server.

$fromEmail = '[email protected]';
$toEmail = '[email protected]';
$mailUser = 'myUsername';
$mailPassword = 'myPassword';
$smtpServer = 'smtp.example.com';
$smtpPort = 587;
$content = 'Email message content';
$subject = 'Email message subject';

$credentials = New-Object System.Net.NetworkCredential $mailUser, $mailPassword;

$server = New-Object System.Net.Mail.SmtpClient $smtpServer, $smtpPort;
$server.UseDefaultCredentials = $false;
$server.EnableSSL = $true;
$server.Credentials = $credentials
$server.Send($fromEmail, $toEmail, $subject, $content);

When I try to run the above in a powershell prompt, it results in an error specifying relay access denied.

Exception calling "Send" with "4" argument(s): "Client does not have permission to submit mail to this server. The
server response was: 4.7.1 <[email protected]>: Relay access denied"
At line:1 char:1
+ $server.Send($fromEmail, $toEmail, $subject, $content);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SmtpException

If I try sending an email using Thunderbird or PHP's Swiftmailer and the same server and credential settings it works fine. From looking at the postfix logs it appears as though the SmtpClient is not even attempting to authenticate but instead just trying to send the mail anonymously.

This is what a good log entry made by thunderbird looks like:

Jun 14 21:17:42 services postfix/submission/smtpd[16653]: connect from unknown[xxxx]
Jun 14 21:17:43 services postfix/submission/smtpd[16653]: 59074F96E: client=unknown[xxxx], sasl_method=PLAIN, [email protected]

Whereas the entry made by SmtpClient looks like:

Jun 14 22:11:16 services postfix/submission/smtpd[16824]: connect from unknown[xxxx]
Jun 14 22:11:16 services postfix/submission/smtpd[16824]: NOQUEUE: reject: RCPT from unknown[xxxx]: 454 4.7.1 <[email protected]>: Relay access denied; from=<[email protected]> to=<[email protected]> proto=ESMTP helo=<WTFv2>

As test I also tried sending via a gmail address using my gmail credentials and that also failed due to no authentication.

Exception calling "Send" with "4" argument(s): "The SMTP server requires a secure connection or the client was not
authenticated. The server response was: 5.5.1 Authentication Required. Learn more at"
At line:1 char:1
+ $server.Send($fromEmail, $toEmail, $subject, $content);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SmtpException

What am I missing here? Why does the .net SmtpClient not send the authentication to allow the mail to go through?


Solution

  • It appears there were at least two issues causing this problem. I ended up trying so many things that I'm not entirely sure what combination finally resolved the issue.

    First, I determined that the problem was due to my server only offering the PLAIN authentication method. It appears that SmtpClient will not use PLAIN even over a TLS enabled connection. If SmtpClient does not support any of the offered authentication methods it apparently just continues on without authentication.

    I tried to find a list of supported authentication methods but was unable too. This blog post lead me to trying NTLM and LOGIN. With NTLM it tried to authenticate but it was unable to successfully. LOGIN worked properly eventually.

    The second part of the issue, I'm not entirely sure what the underlying problem was. Enabling LOGIN did not work initially so I decided to convert the code over to C# and compiled and ran a test program there. That program worked right off the bat. I went back to Powershell and tried my code again to see if I could find a difference and it suddenly started working also.

    Somehow compiling and running the C# version cause the Powershell version to also work. If anyone can explain why this might be I'd love to know.