Search code examples
c#vb.netwinformssmtpclient

Sending emails from a windows forms application


I'm building a windows forms application that's supposed to run on a remote/isolated machine and send error notifications by email to the admins. I've tried employing System.Net.Mail classes to achieve this but I'm running into a strange problem:

1. I get an error message:

System.IO.IOException: Unable to read data from the transport connection: 
An existing connection was forcibly closed by the remote host.--->
System.Net.Sockets.SocketException: An existing connection was forcibly closed by 
the remote host at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, 
Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.
Read(Byte[] buffer, Int32 offset, Int32 size)

2. I tried sniffing the network activity to see what was going wrong. So here's how it goes:

i) The DNS lookup for my SMTP server's hostname works
ii) My application connects to the SMTP server and sends "EHLO MY-HOSTNAME"
iii) SMTP server responds back with it's usual
iv) My application sends "AUTH login abcdxyz" and receives an acknowledgement packet

At this point, it seems that either the SMTP server doesn't seem to request for the password or my machine shuts off the connection to the SMTP server before the SMTP server could request for a password.

I've tried using different SMTP ports and SMTP hosts. Also, I tried disabling my firewall and AV, but no luck. While connecting to my SMTP server using PuTTY and issuing the same sequence of commands as my application does (picked from the packet sniffer), everything works out fine and I'm able to send out the email.

Here's the code that I'm using:

Imports System.Net
Imports System.Net.Mail

Public Function SendMail() As Boolean

     Dim smtpClient As New SmtpClient("smtp.myserver.com", 587) 'I tried using different hosts and ports
     smtpClient.UseDefaultCredentials = False
     smtpClient.Credentials = New NetworkCredential("[email protected]", "password")
     smtpClient.EnableSsl = True 'Also tried setting this to false

     Dim mm As New MailMessage
     mm.From = New MailAddress("[email protected]")
     mm.Subject = "Test Mail"
     mm.IsBodyHtml = True
     mm.Body = "<h1>This is a test email</h1>"
     mm.To.Add("[email protected]")

     Try
          smtpClient.Send(mm)
          MsgBox("SUCCESS!")
     Catch ex As Exception
          MsgBox(ex.InnerException.ToString)
     End Try

     mm.Dispose()
     smtpClient.Dispose()

     Return True

End Function

Any advice?


Solution

  • In C# it works like this:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        private void btnTest_Click(object sender, RoutedEventArgs e)
        {
            MailAddress from = new MailAddress("[email protected]", "Name and stuff");
            MailAddress to = new MailAddress("[email protected]", "Name and stuff");
            List<MailAddress> cc = new List<MailAddress>();
            cc.Add(new MailAddress("[email protected]", "Name and stuff"));
            SendEmail("Want to test this damn thing", from, to, cc);
        }
    
        protected void SendEmail(string _subject, MailAddress _from, MailAddress _to, List<MailAddress> _cc, List<MailAddress> _bcc = null)
        {
            string Text = "";
            SmtpClient mailClient = new SmtpClient("Mailhost");
            MailMessage msgMail;
            Text = "Stuff";
            msgMail = new MailMessage();
            msgMail.From = _from;
            msgMail.To.Add(_to);
            foreach (MailAddress addr in _cc)
            {
                msgMail.CC.Add(addr);
            }
            if (_bcc != null)
            {
                foreach (MailAddress addr in _bcc)
                {
                    msgMail.Bcc.Add(addr);
                }
            }
            msgMail.Subject = _subject;
            msgMail.Body = Text;
            msgMail.IsBodyHtml = true;
            mailClient.Send(msgMail);
            msgMail.Dispose();
        }
    }
    

    Do not forget the using System.Net.Mail;

    I Think in VB it works like this to, here is the code, it might have some errors, I don't often write in vb.net:

    Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim _from As New MailAddress("[email protected]", "Name and stuff")
        Dim _to As New MailAddress("[email protected]", "Name and stuff")
        Dim cc As New List(Of MailAddress)
        cc.Add(New MailAddress("[email protected]", "Name and stuff"))
        SendEmail("Wan't to test this thing", _from, _to, cc)
    End Sub
    
    Protected Sub SendEmail(ByVal _subject As String, ByVal _from As MailAddress, ByVal _to As MailAddress, ByVal _cc As List(Of MailAddress), Optional ByVal _bcc As List(Of MailAddress) = Nothing)
    
        Dim Text As String = ""
        Dim mailClient As New SmtpClient("Mailhost")
        Dim msgMail As MailMessage
        Text = "Stuff"
        msgMail = New MailMessage()
        msgMail.From = _from
        msgMail.To.Add(_to)
        For Each addr As MailAddress In _cc
            msgMail.CC.Add(addr)
        Next
        If _bcc IsNot Nothing Then
            For Each addr As MailAddress In _bcc
                msgMail.Bcc.Add(addr)
            Next
        End If
        msgMail.Subject = _subject
        msgMail.Body = Text
        msgMail.IsBodyHtml = True
        mailClient.Send(msgMail)
        msgMail.Dispose()
    End Sub
    

    Do not forget to import System.Net.Mail