Modules/Messaging/MailSender.vb

246 lines
8.8 KiB
VB.net

Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base
Imports System.Net.Security
Imports Limilabs.Client.SMTP
Imports Limilabs.Client
Public Class MailSender
Inherits BaseClass
Private Server As String
Private Port As Integer
Private User As String
Private Password As String
Private AuthType As String
Private Session As Smtp = Nothing
Const SMTP_IGNORED_ERRORS As SslPolicyErrors =
SslPolicyErrors.RemoteCertificateChainErrors Or ' self-signed
SslPolicyErrors.RemoteCertificateNameMismatch ' name mismatch
Public Sub New(pLogConfig As LogConfig)
MyBase.New(pLogConfig)
End Sub
''' <summary>
''' Start a connection with the specified server and return the SMTP client. Throws if there was an error.
''' </summary>
''' <param name="pServer"></param>
''' <param name="pPort"></param>
''' <param name="pUser"></param>
''' <param name="pPassword"></param>
''' <param name="pAuthType"></param>
''' <returns></returns>
Public Function ConnectToServer(pServer As String, pPort As Integer, pUser As String, pPassword As String, pAuthType As String) As Boolean
Server = pServer
Port = pPort
User = pUser
Password = pPassword
AuthType = pAuthType
Logger.Debug("Connecting to Server..")
Logger.Debug("SMTP Server: [{0}]", Server)
Logger.Debug("SMTP Port: [{0}]", Port)
Logger.Debug("SMTP User: [{0}]", User)
Logger.Debug("SMTP AuthType: [{0}]", AuthType)
Dim oSession As New Smtp()
AddHandler oSession.ServerCertificateValidate, AddressOf Session_ServerCertificateValidate
Logger.Debug("Initializing Connection with Auth type [{0}].", pAuthType)
If pAuthType = "SSL" Then
Try
If pPort = 465 Then
Logger.Debug("Connecting with [ConnectSSL] on [{0}/{1}]", pServer, pPort)
oSession.ConnectSSL(pServer)
Else
Logger.Debug("Connecting with [Connect] on [{0}/{1}]", pServer, pPort)
oSession.Connect(pServer, pPort)
End If
Logger.Info("Connection Successful!")
Catch ex As Exception
Logger.Warn("Error while connecting with Auth type SSL!")
Logger.Error(ex)
Return False
End Try
ElseIf AuthType = "SSL/TLS" Or AuthType = "STARTTLS" Then
Try
Logger.Debug("Connecting with [Connect] on [{0}/{1}]", pServer, pPort)
oSession.Connect(pServer, pPort)
Logger.Info("Connection Successful!")
Dim oSupportsSTARTTLS As Boolean = oSession.SupportedExtensions.Contains(Limilabs.Client.SMTP.SmtpExtension.StartTLS)
Logger.Debug("Server supports STARTTLS: [{0}]", oSupportsSTARTTLS)
If oSupportsSTARTTLS Then
oSession.StartTLS()
Logger.Info("STARTTLS Successful!")
Else
Logger.Debug("Server does not support STARTTLS. Enabling TLS1.2 instead.")
oSession.SSLConfiguration.EnabledSslProtocols = Security.Authentication.SslProtocols.Tls12
End If
Catch ex As Exception
Logger.Warn("Error while connecting with Auth type STARTTLS!")
Logger.Error(ex)
Return False
End Try
Else
Try
Logger.Debug("Unknown Auth type. Using PLAINTEXT connection.")
oSession.Connect(pServer)
Logger.Info("Connection Successful!")
Catch ex As Exception
Logger.Warn("Error while connecting with Auth type PLAINTEXT!")
Logger.Error(ex)
Return False
End Try
End If
Try
If pUser <> String.Empty Then
Logger.Info("Logging in with user [{0}]", pUser)
oSession.UseBestLogin(pUser, pPassword)
End If
Catch ex As Exception
Logger.Warn("Error while connecting with Auth type PLAINTEXT!")
Logger.Error(ex)
Return False
End Try
Session = oSession
Return True
End Function
Public Function DisconnectFromServer() As Boolean
Try
If Session IsNot Nothing Then
Logger.Debug("Closing connection to Server [{0}].", Server)
Session.Close()
Session = Nothing
Logger.Info("Connection to Server [{0}] closed.", Server)
Else
Logger.Debug("No connection currently open. Exiting.")
End If
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Private Sub Session_ServerCertificateValidate(sender As Object, e As ServerCertificateValidateEventArgs)
' i dont know why it works but it does
If (e.SslPolicyErrors And Not SMTP_IGNORED_ERRORS) = SslPolicyErrors.None Then
e.IsValid = True
Return
End If
e.IsValid = False
End Sub
Public Function SendMail(pSendTo As List(Of String), pSendFrom As String, pSubject As String, pBody As String, pCreationTime As Date, pAttachments As List(Of String), pTest As Boolean) As Boolean
Dim oSuccessfulSends As New List(Of String)
Dim oFailedSends As New List(Of String)
For Each oSendToAddress In pSendTo
Dim oResult = SendMailTo(Session, oSendToAddress, pSendFrom, pSubject, pBody, pCreationTime, pAttachments, pTest)
If oResult = True Then
oSuccessfulSends.Add(oSendToAddress)
Else
oFailedSends.Add(oSendToAddress)
End If
Next
Logger.Debug("Sent [{0}] mails.", pSendTo.Count)
Logger.Debug("Successful [{0}]", oSuccessfulSends.Count)
Logger.Debug("Failed [{0}]", oFailedSends.Count)
Return True
End Function
Private Function SendMailTo(pSession As Smtp, pSendTo As String, pSendFrom As String, pSubject As String, pBody As String, pCreationTime As Date, pAttachments As List(Of String), pTest As Boolean)
Try
Logger.Debug("Preparing to send mail to [{0}]", pSendTo)
Dim oMailBuilder As New Limilabs.Mail.MailBuilder()
oMailBuilder.From.Add(New Limilabs.Mail.Headers.MailBox(pSendFrom))
oMailBuilder.To.Add(New Limilabs.Mail.Headers.MailBox(pSendTo))
oMailBuilder.Subject = pSubject
Logger.Debug("Setting body for mail")
SetBody(oMailBuilder, pBody, pCreationTime, pTest)
Logger.Debug("Adding [{0}] attachments to mail", pAttachments.Count)
oMailBuilder = AddAttachments(oMailBuilder, pAttachments)
Logger.Debug("Now sending mail..")
Dim oMail = oMailBuilder.Create()
pSession.SendMessage(oMail)
Logger.Info("Mail to [{0}] has been sent.", pSendTo)
Return True
Catch ex As Exception
Logger.Warn("Error while sending mail to [{0}]", pSendTo)
Logger.Error(ex)
Return False
End Try
End Function
Private Function SetBody(pMailBuilder As Limilabs.Mail.MailBuilder, pBody As String, pCreationTime As Date, pTest As Boolean) As Limilabs.Mail.MailBuilder
If pCreationTime <> Date.MinValue Then
pBody &= $"<p>Creation-time: {pCreationTime}</p>"
End If
If pTest Then
pBody = $"<p>This Is a Testmail!<br/>
The body-text will be replaced within profile!<br/>
Server/Port: {Server}/{Port}<br/>
User: {User}<br/>
Password: XXXX<br/>
Auth Type: {AuthType}</p>"
End If
Logger.Debug("Final Mailbody is: [{0}]", pBody)
pMailBuilder.Html = pBody
Return pMailBuilder
End Function
Private Function AddAttachments(pMailBuilder As Limilabs.Mail.MailBuilder, pAttachments As List(Of String)) As Limilabs.Mail.MailBuilder
For Each oAttachment In pAttachments
Try
' Read attachment from disk, add it to Attachments collection
If IO.File.Exists(oAttachment) Then
Logger.Debug("Adding attachment [{0}] to mail.", oAttachment)
pMailBuilder.AddAttachment(oAttachment)
Else
Logger.Warn("Attachment [{0}] does not exist. Skipping.", oAttachment)
End If
Catch ex As Exception
Logger.Warn("Could not read or add attachment [{0}]!", oAttachment)
Logger.Error(ex)
End Try
Next
Return pMailBuilder
End Function
End Class