hello fellow :) i am having a trouble on how can i retry sending failed email recipients. i am trying to make an application in vbnet where i can send emails to multiple address.
some code snippet:
Dim SmtpServer As New SmtpClient()
SmtpServer.Credentials = New Net.NetworkCredential(xInformation(0), xInformation(1))
SmtpServer.Port = CInt(xInformation(2))
SmtpServer.Host = xInformation(3)
SmtpServer.EnableSsl = True
Dim mail As New MailMessage()
mail = New MailMessage
mail.From = New MailAddress(xInformation(4), "Display Name")
mail.CC.Add(xInformation(5)) ' i will make a loop here to add recipients
mail.Subject = xInformation(6)
mail.IsBodyHtml = True
mail.Body = xInformation(7)
SmtpServer.Send(mail)
question arises:
1.) if i have to send, for instance, email to 5 recipients, and only
3 emails have been successfully sent, how can i know the
failed email addresses?
2.) where is the failed email address stored?
3.) what exceptions are needed to trapped this error?
I don't think you can catch these exceptions in your code, the emails that do not get sent you will want to check on the smtp server there should be a mail folder within inetpub
\\ServerName\c$\Inetpub\mailroot
Inside of this folder you should find a folder called: BadMail and Drop please look at the contents of these. Your VB code doesn't have access to what a valid email address might be, only that it will try to send an smtp email message, if it fails then the SMTP application handles that.
Per your comment:
Imports System.Net.Mail
Imports System.Threading
Imports System.Web.Configuration
''' <summary>
''' Provides a method for sending email.
''' </summary>
Public NotInheritable Class Email
Private Sub New()
End Sub
''' <summary>
''' Constructs and sends an email message.
''' </summary>
''' <param name="fromName">The display name of the person the email is from.</param>
''' <param name="fromEmail">The email address of the person the email is from.</param>
''' <param name="subject">The subject of the email.</param>
''' <param name="body">The body of the email.</param>
Public Shared Sub Send(fromName As String, fromEmail As String, subject As String, body As String)
Dim message As New MailMessage() With { _
Key .IsBodyHtml = False, _
Key .From = New MailAddress(fromEmail, fromName), _
Key .Subject = subject, _
Key .Body = body _
}
message.[To].Add(WebConfigurationManager.AppSettings("mailToAddresses"))
Dim originalRecipientCount As Integer = message.[To].Count
Dim failOnAnyAddress As Boolean = Convert.ToBoolean(WebConfigurationManager.AppSettings("failOnAnyAddress"))
Try
Send(message)
Catch generatedExceptionName As SmtpFailedRecipientException
If message.[To].Count = originalRecipientCount Then
' all recipients failed
Throw
End If
If failOnAnyAddress Then
' some (not ALL) recipients failed
Throw
End If
End Try
End Sub
Private Shared Sub Send(message As MailMessage)
Dim client As New SmtpClient()
Try
client.Send(message)
Catch ex As SmtpFailedRecipientsException
' multiple fail
message.[To].Clear()
For Each sfrEx As SmtpFailedRecipientException In ex.InnerExceptions
CheckStatusAndReaddress(message, sfrEx)
Next
If message.[To].Count > 0 Then
' wait 5 seconds, try a second time
Thread.Sleep(5000)
client.Send(message)
Else
Throw
End If
Catch ex As SmtpFailedRecipientException
' single fail
message.[To].Clear()
CheckStatusAndReaddress(message, ex)
If message.[To].Count > 0 Then
' wait 5 seconds, try a second time
Thread.Sleep(5000)
client.Send(message)
Else
Throw
End If
Finally
message.Dispose()
End Try
End Sub
Private Shared Sub CheckStatusAndReaddress(message As MailMessage, exception As SmtpFailedRecipientException)
Dim statusCode As SmtpStatusCode = exception.StatusCode
If statusCode = SmtpStatusCode.MailboxBusy OrElse statusCode = SmtpStatusCode.MailboxUnavailable OrElse statusCode = SmtpStatusCode.TransactionFailed Then
message.[To].Add(exception.FailedRecipient)
End If
End Sub
End Class
Convert any code from C# to vb.net: http://www.developerfusion.com/tools/convert/csharp-to-vb/
Related
I am having problems getting a file handle to close properly. I have tried to use an additional Mutex to ensure only one thread has access to this file at a time.
As far as I understand it the Using construct should ensure that the file handle is released properly, and the Mutex should ensure that this code can only run in 1 thread at a time.
The error occurs when the logger is called multiple times in rapid succession.
The gethashcode was an attempt to verify that the mutex instance is the same.
Error Message:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
The process cannot access the file '****\LOG.log' because it is being used by another process.
Source:
Imports System.IO
Imports System.Net.Mail
Imports System.Threading
Public NotInheritable Class FileLogger
Private Shared ReadOnly _instance As New Lazy(Of FileLogger)(Function() New FileLogger(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)
Public LOG_LEVEL As Integer = 4
Public LEVELS As New Dictionary(Of Double, String)
Private Shared strFile As String = "LOG.log"
Public Shared FileLoc As New Mutex()
Public Shared ReadOnly Property getLogger() As FileLogger
Get
Return _instance.Value
End Get
End Property
Private Sub New()
Dim strFile As String = "yourfile.log"
LEVELS.Add(0, "FATAL ")
LEVELS.Add(1, "CRITICAL")
LEVELS.Add(2, "ERROR ")
LEVELS.Add(3, "INFO ")
LEVELS.Add(4, "DEBUG ")
LEVELS.Add(2.5, "WARNING ")
End Sub
Public Sub writeEntry(ByVal message As String, ByVal level As Double)
If level <= LOG_LEVEL Then
Dim log_str As String = String.Format("{0} - in: {3} - {1}: {2}", DateTime.Now.ToString, LEVELS(level), message, Thread.CurrentThread.ManagedThreadId)
Console.WriteLine(log_str)
If level < 3 Then ' warning or greater write to file else just console
Console.WriteLine(FileLoc.GetHashCode())
FileLoc.WaitOne(Timeout.Infinite)
Using sw As StreamWriter = New StreamWriter(strFile, True) '<-- Debugger points to this line
sw.WriteLine(log_str)
End Using
FileLoc.ReleaseMutex()
End If
If level <= 2 Then 'if error or greater send email
FileLoc.WaitOne(Timeout.Infinite)
Dim mail As New MailMessage
mail.To.Add("email")
mail.From = New MailAddress("email")
mail.Subject = "Error on MC Server (SERVERNAME)"
mail.Body = log_str
mail.IsBodyHtml = True
mail.Attachments.Add(New Attachment(strFile))
Dim smtp As New SmtpClient
smtp.Host = "IPADDR"
smtp.Send(mail)
FileLoc.ReleaseMutex()
End If
End If
End Sub
End Class
The email section was not closing the file correctly. wrapping this in a using construct fixed the issue.
I also ended up implementing the SyncLock construct around the entire operation.
as some of the comments have pointed out the mutex may or may not have been doing what it was supposed to, but the file handle was still open from the attachment operation.
Public Sub writeEntry(ByVal message As String, ByVal level As Double)
SyncLock FileLoc
If level <= LOG_LEVEL Then
Dim log_str As String = String.Format("{0} - in: {3} - {1}: {2}", DateTime.Now.ToString, LEVELS(level), message, Thread.CurrentThread.ManagedThreadId)
Console.WriteLine(log_str)
If level < 3 Then ' warning or greater write to file else just console
Console.WriteLine(FileLoc.GetHashCode())
Using sw As StreamWriter = New StreamWriter(strFile, True)
sw.WriteLine(log_str)
End Using
End If
If level <= 2 Then 'if error or greater send email
Using at As Attachment = New Attachment(strFile)
Dim mail As New MailMessage
mail.To.Add("email")
mail.From = New MailAddress("email")
mail.Subject = "Error on MC Server (servername)"
mail.Body = log_str
mail.IsBodyHtml = True
mail.Attachments.Add(at)
Dim smtp As New SmtpClient
smtp.Host = "IPADDR"
smtp.Send(mail)
End Using
End If
End If
End SyncLock
End Sub
I am able to successfully connect to the Google Calendar API and sync events when running locally on my machine. However when the web application runs on the server I get the following error:
No application is associated with the specified file for this operation
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.<AuthorizeAsync>d__1.MoveNext()
I don't understand why it is having trouble with file associations since I am not using a FileDataStore but a database to store the data. Everything is functional when using Visual Studio in Debug Mode on the local machine but the error happens when uploaded to the production server.
This is the code I am using to connect to the API:
Private Shared Function BuildService(EmployeeID As String) As Google.Apis.Calendar.v3.CalendarService
'// Google OAuth for User Calendar
Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(New ClientSecrets() With { _
.ClientId = GoogleAPI.ClientID, _
.ClientSecret = GoogleAPI.ClientSecret _
}, New String() {Google.Apis.Calendar.v3.CalendarService.Scope.Calendar}, EmployeeID, CancellationToken.None, New GoogleDataStore()).Result
' Create the service.
Dim service = New Google.Apis.Calendar.v3.CalendarService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = credential, _
.ApplicationName = "Influence Calandar App" _
})
Return service
End Function
This is the GoogleDataStore class I am using to implement IDataStore:
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports Google.Apis.Util.Store
Imports System.Data.SqlClient
Imports System.Threading.Tasks
Imports Google.Apis.Json
Public Class GoogleDataStore
Implements IDataStore
''' <summary>Gets the full folder path.</summary>
Private Property _ConnectionExists() As [Boolean]
Get
Return m__ConnectionExists
End Get
Set(value As [Boolean])
m__ConnectionExists = Value
End Set
End Property
Private m__ConnectionExists As [Boolean]
Public ReadOnly Property connectionExists() As [Boolean]
Get
Return _ConnectionExists
End Get
End Property
''' <summary>
''' Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist
''' yet) under the current directory
''' </summary>
''' <param name="folder">Folder name</param>
Public Sub New()
Dim myConnection As SqlConnection = Me.connectdb()
' Opens a connection to the database.
If _ConnectionExists Then
' check if the Table Exists;
Try
Dim myReader As SqlDataReader = Nothing
Dim myCommand As New SqlCommand("select 1 from GoogleUser where 1 = 0", myConnection)
myReader = myCommand.ExecuteReader()
While myReader.Read()
Dim hold = myReader("Column1")
End While
Catch
' table doesn't exist we create it
Dim myCommand As New SqlCommand("CREATE TABLE [dbo].[GoogleUser]( " + " [username] [nvarchar](4000) NOT NULL," + " [RefreshToken] [nvarchar](4000) NOT NULL," + " [Userid] [nvarchar](4000) NOT NULL" + " ) ON [PRIMARY]", myConnection)
myCommand.ExecuteNonQuery()
End Try
End If
myConnection.Close()
End Sub
''' <summary>
''' Stores the given value for the given key. It creates a new file (named <see cref="GenerateStoredKey"/>) in
''' <see cref="FolderPath"/>.
''' </summary>
''' <typeparam name="T">The type to store in the data store</typeparam>
''' <param name="key">The key</param>
''' <param name="value">The value to store in the data store</param>
Public Function StoreAsync(Of T)(key As String, value As T) As Task Implements IDataStore.StoreAsync
If String.IsNullOrEmpty(key) Then
Throw New ArgumentException("Key MUST have a value")
End If
Dim serialized = NewtonsoftJsonSerializer.Instance.Serialize(value)
Dim myConnection As SqlConnection = Me.connectdb()
If Not _ConnectionExists Then
Throw New Exception("Not connected to the database")
End If
' Try and find the Row in the DB.
Using command As New SqlCommand("select Userid from GoogleUser where UserName = #username", myConnection)
command.Parameters.AddWithValue("#username", key)
Dim hold As String = Nothing
Dim myReader As SqlDataReader = command.ExecuteReader()
While myReader.Read()
hold = myReader("Userid").ToString()
End While
myReader.Close()
If hold Is Nothing Then
Try
' New User we insert it into the database
Dim insertString As String = "INSERT INTO [dbo].[GoogleUser] ([username],[RefreshToken],[Userid]) " + " VALUES (#key,#value,'1' )"
Dim commandins As New SqlCommand(insertString, myConnection)
commandins.Parameters.AddWithValue("#key", key)
commandins.Parameters.AddWithValue("#value", serialized)
commandins.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception("Error inserting new row: " + ex.Message)
End Try
Else
Try
' Existing User We update it
Dim insertString As String = "update [dbo].[GoogleUser] " + " set [RefreshToken] = #value " + " where username = #key"
Dim commandins As New SqlCommand(insertString, myConnection)
commandins.Parameters.AddWithValue("#key", key)
commandins.Parameters.AddWithValue("#value", serialized)
commandins.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception("Error updating user: " + ex.Message)
End Try
End If
End Using
myConnection.Close()
Return TaskEx.Delay(0)
End Function
''' <summary>
''' Deletes the given key. It deletes the <see cref="GenerateStoredKey"/> named file in <see cref="FolderPath"/>.
''' </summary>
''' <param name="key">The key to delete from the data store</param>
Public Function DeleteAsync(Of T)(key As String) As Task Implements IDataStore.DeleteAsync
If String.IsNullOrEmpty(key) Then
Throw New ArgumentException("Key MUST have a value")
End If
Dim myConnection As SqlConnection = Me.connectdb()
If Not _ConnectionExists Then
Throw New Exception("Not connected to the database")
End If
' Deletes the users data.
Dim deleteString As String = "delete [dbo].[GoogleUser] from " + " where username = #key"
Dim commandins As New SqlCommand(deleteString, myConnection)
commandins.Parameters.AddWithValue("#key", key)
commandins.ExecuteNonQuery()
myConnection.Close()
Return TaskEx.Delay(0)
End Function
''' <summary>
''' Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
''' in <see cref="FolderPath"/> doesn't exist.
''' </summary>
''' <typeparam name="T">The type to retrieve</typeparam>
''' <param name="key">The key to retrieve from the data store</param>
''' <returns>The stored object</returns>
Public Function GetAsync(Of T)(key As String) As Task(Of T) Implements IDataStore.GetAsync
'Key is the user string sent with AuthorizeAsync
If String.IsNullOrEmpty(key) Then
Throw New ArgumentException("Key MUST have a value")
End If
Dim tcs As New TaskCompletionSource(Of T)()
' Note: create a method for opening the connection.
Dim myConnection As SqlConnection = Me.connectdb()
' Try and find the Row in the DB.
Using command As New SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection)
command.Parameters.AddWithValue("#username", key)
Dim RefreshToken As String = Nothing
Dim myReader As SqlDataReader = command.ExecuteReader()
While myReader.Read()
RefreshToken = myReader("RefreshToken").ToString()
End While
If RefreshToken Is Nothing Then
' we don't have a record so we request it of the user.
tcs.SetResult(Nothing)
Else
Try
' we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize(Of T)(RefreshToken))
Catch ex As Exception
tcs.SetException(ex)
End Try
End If
End Using
Return tcs.Task
End Function
''' <summary>
''' Clears all values in the data store. This method deletes all files in <see cref="FolderPath"/>.
''' </summary>
Public Function ClearAsync() As Task Implements IDataStore.ClearAsync
Dim myConnection As SqlConnection = Me.connectdb()
If Not _ConnectionExists Then
Throw New Exception("Not connected to the database")
End If
' Removes all data from the Table.
Dim truncateString As String = "truncate table [dbo].[GoogleUser] "
Dim commandins As New SqlCommand(truncateString, myConnection)
commandins.ExecuteNonQuery()
myConnection.Close()
Return TaskEx.Delay(0)
End Function
''' <summary>Creates a unique stored key based on the key and the class type.</summary>
''' <param name="key">The object key</param>
''' <param name="t">The type to store or retrieve</param>
Public Shared Function GenerateStoredKey(key As String, t As Type) As String
Return String.Format("{0}-{1}", t.FullName, key)
End Function
'Handel's creating the connection to the database
Private Function connectdb() As SqlConnection
Dim myConnection As SqlConnection = Nothing
Try
myConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("db1251ConnectionString").ConnectionString)
Try
myConnection.Open()
' ensuring that we are able to make a connection to the database.
If myConnection.State = System.Data.ConnectionState.Open Then
_ConnectionExists = True
Else
Throw New ArgumentException("Error unable to open connection to the database.")
End If
Catch ex As Exception
Throw New ArgumentException("Error opening Connection to the database: " + ex.Message)
End Try
Catch ex As Exception
Throw New ArgumentException("Error creating Database Connection: " + ex.Message)
End Try
Return myConnection
End Function
End Class
Any help would be appreciated. I have been trying to figure out the error but have had no luck so far. None of the other posts on "No application is associated with the specified file for this operation" have been helpful so far since I am not trying to access files. Is "GoogleWebAuthorizationBroker" trying to open a file despite being told to use the GoogleDataStore class instead of the FileDataStore, and if so how do I stop it?
I am running a vb.net web application hosted on a VM with Windows Azure.
I was finally able to get it working by switching from GoogleWebAuthorizationBroker to GoogleAuthorizationCodeFlow for authentication.
Hopefully the code below will help you if you get the same error.
Private Sub GetGoogleService()
Dim datafolder As String = Server.MapPath("App_Data/CalendarService.api.auth.store")
Dim scopes As IList(Of String) = New List(Of String)()
Dim UserId As String = aMP.currentEmployeeID
scopes.Add(Google.Apis.Calendar.v3.CalendarService.Scope.Calendar)
Dim myclientsecret As New ClientSecrets() With { _
.ClientId = GoogleAPI.ClientID, _
.ClientSecret = GoogleAPI.ClientSecret _
}
Dim flow As GoogleAuthorizationCodeFlow
flow = New GoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer() With { _
.DataStore = New FileDataStore(datafolder), _
.ClientSecrets = myclientsecret, _
.Scopes = scopes _
})
Dim uri As String = Request.Url.ToString()
Dim code = Request("code")
If code IsNot Nothing Then
Dim token = flow.ExchangeCodeForTokenAsync(UserId, code, uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result
' Extract the right state.
Dim oauthState = AuthWebUtility.ExtracRedirectFromState(flow.DataStore, UserId, Request("state")).Result
Response.Redirect(oauthState)
Else
Dim result = New AuthorizationCodeWebApp(flow, uri, uri).AuthorizeAsync(UserId, CancellationToken.None).Result
If result.RedirectUri IsNot Nothing Then
' Redirect the user to the authorization server.
Response.Redirect(result.RedirectUri)
Else
' The data store contains the user credential, so the user has been already authenticated.
'Response.Write("User Already Authorized")
Me.isConnected = New Google.Apis.Calendar.v3.CalendarService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = result.Credential, _
.ApplicationName = "Calandar App" _
})
End If
End If
End Sub
I'm currently working on a UDP communication PC <-> ARM LM3S6965 (Luminary) through the Ethernet. On the PC there is a VB.net application that simulates a UDP server/client.
the message is broadcasted from Vb.net application to ARM LM3S6965 based device, and in return response is sent from ARM Device to vb.net application.
but sometimes receive UdpClient throws socket exception i.e. Only one usage of each socket address (protocol/network address/port) is normally permitted.
the line which throws exception is
udpReceivingClient = New UdpClient(mnPort)
Complete VB.net Code is as follows
Module mod_Search_UDP
Public mnPort As Int32 = 3040 'Port number to send/recieve data on
'Public Const msBroadcastAddress As String = "255.255.255.255" 'Sends data to all LOCAL listening clients, to send data over WAN you'll need to enter a public (external) IP address of the other client
'Dim endPoint As IPEndPoint = New IPEndPoint(msBroadcastAddress, mnPort)
Public udpReceivingClient As UdpClient 'Client for handling incoming data
Public udpSendingClient As UdpClient 'Client for sending data
Public receivingThread As Thread 'Create a separate thread to listen for incoming data, helps to prevent the form from freezing up
Public mbiClosing As Boolean = False 'Used to close clients if form is closing
Public mbiCloseRxClient As Boolean = False
Public Sub InitializeSender()
Dim soc As Socket
Dim lsPort As String
Dim lnPort As Int32 = 3040
Const lsBroadcastAdd As String = "255.255.255.255"
'Dim endPoint As IPEndPoint = New IPEndPoint(msBroadcastAddress, mnPort)
'udpSendingClient = New UdpClient(endPoint)
udpSendingClient = New UdpClient(lsBroadcastAdd, lnPort)
udpSendingClient.EnableBroadcast = True
soc = udpSendingClient.Client
lsPort = (CType(soc.LocalEndPoint, IPEndPoint).Port.ToString())
mnPort = Convert.ToInt32(lsPort)
End Sub
Public Sub InitializeReceiver()
'Create UdpClient class and bind it to the local port number provided
'Try
udpReceivingClient = New UdpClient(mnPort)
'udpReceivingClient.EnableBroadcast = True
mbiCloseRxClient = True
'Catch ex As Exception
' MsgBox(ex.ToString)
'End Try
Dim start As ThreadStart = New ThreadStart(AddressOf MT_Receiver)
receivingThread = New Thread(start)
receivingThread.IsBackground = True
receivingThread.Start()
End Sub
Public Sub MT_Receiver()
Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, mnPort) 'Listen for incoming data from any IP address on the specified port
Dim lbData() As Byte 'Buffer for storing incoming bytes
Dim llRet As UInt16
'udpListen.Poll(1000, Net.Sockets.SelectMode.SelectRead)
While (True) 'Setup an infinite loop
If mbiClosing = True Then 'Exit sub if form is closing
Exit Sub
End If
llRet = udpReceivingClient.Available
If llRet > 0 Then
lbData = udpReceivingClient.Receive(endPoint) 'Receive incoming bytes
'If udpListen.Available Then
' udpListen.Receive(lbData, 256, Net.Sockets.SocketFlags.None)
'End If
'If lbData Is Nothing Then
'Else
frmSearchUDP.MT_Validate_Msg(lbData)
End If
End While
End Sub
Public Sub MT_Send_UDP(ByVal lbTxBuffer() As Byte)
InitializeSender()
If mbiCloseRxClient = True Then
receivingThread.Abort()
udpReceivingClient.Client.Dispose()
udpReceivingClient.Close()
End If
Try
udpSendingClient.Send(lbTxBuffer, lbTxBuffer.Length)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
udpSendingClient.Client.Dispose()
udpSendingClient.Close()
InitializeReceiver()
'Try
' udpReceivingClient.BeginReceive(AddressOf MT_RX_Callback, Nothing)
'Catch ex As Exception
' MsgBox(ex.ToString)
'End Try
End Sub
End Module
Whats mistake is there in code ? how can i use same port for receive and transmit ?
I am using SMTP server to send emails.
I would like to get an error message when the SMTP server is down or when the email was not delivered.
With DeliveryNotificationOptions.OnFailure I get an email that the email has not been delivered.
I would like to get an error. Is this possible?
How I can check if SMTP is running?
Here is the code I use:
Dim serverName As String = ""
Dim mailSenderInstance As SmtpClient = Nothing
Dim AnEmailMessage As New MailMessage
Dim sendersEmail As String = ""
Try
serverName = GetServerName("EMAIL_SERVER")
mailSenderInstance = New SmtpClient(serverName, 25)
sendersEmail = GetSendersEmail(msUserName)
AnEmailMessage.From = New MailAddress(sendersEmail)
'MAIL DETAILS
AnEmailMessage.Subject = "New Email"
AnEmailMessage.Body = "The Message"
AnEmailMessage.To.Add(anEmailAddress)
' Delivery notifications
AnEmailMessage.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
mailSenderInstance.UseDefaultCredentials = True 'False
mailSenderInstance.Send(AnEmailMessage)
Catch ex As System.Exception
MessageBox.Show(ex.ToString)
Finally
AnEmailMessage.Dispose()
mailSenderInstance.Dispose()
End Try
add another try catch block around your SMTP declaration
try
mailSenderInstance = New SmtpClient(serverName, 25)
catch ex as exception
msgbox( "Error creating SMTP connection: " & ex.message)
end try
regards
ok, you want to know the SMTP status. SMTP runs as a Service. I've written a function for you to know status of ANY service in the system. Add reference to "System.ServiceProcess" to your project.
''response: -1 = service missing, 0 = stopped or stopping, 1 = running
imports System.ServiceProcess ''add this at top
Private Function GetServiceStatus(ByVal svcName As String) As Integer
Dim retVal As Integer
Dim sc As New ServiceController(svcName)
Try
If sc.Status.Equals(ServiceControllerStatus.Stopped) Or sc.Status.Equals(ServiceControllerStatus.StopPending) Then
retVal = 0
Else
retVal = 1
End If
Catch ex As Exception
retVal = -1
End Try
Return retVal
End Function
use it like this:
'' use taskManager to figure correct service name
dim svStatus as integer = GetServiceStatus("SMTP")
if svStatus <> 1 then
msgbox("Service not running or absent")
else
''write your send mail code here
end if
hope this will help you
I want to send an email, but it gives me an error.
I have this code:
Sub sendMail(ByVal title As String, ByVal content As String)
Dim SmtpServer As New SmtpClient("smtp.gmail.com", 25)
SmtpServer.Credentials = New Net.NetworkCredential("name#gmail.com", "password")
Dim mail As New MailMessage("name#gmail.com", "name#gmail.com", title, content)
SmtpServer.Send(mail)
End Sub
I have a try catch which tries to call this method, it doesnt work so the catch runs and i get thes exception: System.Net.Mail.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. b6sm3176487lae.0 - gsmtp Why do I get this error? and how do I fix it?
Gmail uses SMTP over SSL on port 465.
Try doing:
Dim SmtpServer As New SmtpClient("smtp.gmail.com", 465)
...
SmtpServer.EnableSsl = True
...
Try this - I know it works.
Dim Mail As New MailMessage
Dim SMTP As New SmtpClient("smtp.gmail.com")
Mail.Subject = "Security Update"
Mail.From = New MailAddress("name#gmail.com")
SMTP.Credentials = New System.Net.NetworkCredential("name#gmail.com", "password") '<-- Password Here
Mail.To.Add(address & "#gmail.com") 'I used ByVal here for address
Mail.Body = "" 'Message Here
SMTP.EnableSsl = True
SMTP.Port = "587"
SMTP.Send(Mail)
There is some problem with google account, you need to switch off some security settings. After sending email over and over, I received email on one of my support account (for google), the email were:
You recently changed your security settings so that your Google Account [trdjoko#gmail.com] is no longer protected by modern security standards.
If you did not make this change
Please review your Account Activity page at https://security.google.com/settings/security/activity to see if anything looks suspicious. Whoever made the change knows your password; we recommend that you change it right away.
If you made this change
Please be aware that it is now easier for an attacker to break into your account. You can make your account safer again by undoing this change at https://www.google.com/settings/security/lesssecureapps then switching to apps made by Google such as Gmail to access your account.
Sincerely,
The Google Accounts team
So I switched of additional security and i worked fine.
Change the port to 587. Port 25 does not support SSL.
A super easy way of doing this(without changing any security settings) is by using IFTTT and my IFTTT Maker.net libary
First, in IFTTT create a new recipe that's triggered by the Maker channel and name the event "send_gmail".
Then, select the Gmail engine and click "Send an email", and replace To with {{value1}}, subject with {{value2}} and message/body with {{value3}}
After that, in Visual studio, add ifttt.vb to your project. Now for the code:
Try
makechannel.scode = "your account ID"
makechannel.fireevent("send_gmail", "TO", "SUBJECT", "MESSAGE")
'code goes here if done
Catch ex As Exception
'code goes here if it fails
End Try
Then fill in your account ID. You can find it at ifttt.com/maker
And that's it!
I Have written the class which can perform this task easyly.
Imports System.Net.Mail
Public Class GGSMTP_GMAIL
Dim Temp_GmailAccount As String
Dim Temp_GmailPassword As String
Dim Temp_SMTPSERVER As String
Dim Temp_ServerPort As Int32
Dim Temp_ErrorText As String = ""
Dim Temp_EnableSSl As Boolean = True
Public ReadOnly Property ErrorText() As String
Get
Return Temp_ErrorText
End Get
End Property
Public Property EnableSSL() As Boolean
Get
Return Temp_EnableSSl
End Get
Set(ByVal value As Boolean)
Temp_EnableSSl = value
End Set
End Property
Public Property GmailAccount() As String
Get
Return Temp_GmailAccount
End Get
Set(ByVal value As String)
Temp_GmailAccount = value
End Set
End Property
Public Property GmailPassword() As String
Get
Return Temp_GmailPassword
End Get
Set(ByVal value As String)
Temp_GmailPassword = value
End Set
End Property
Public Property SMTPSERVER() As String
Get
Return Temp_SMTPSERVER
End Get
Set(ByVal value As String)
Temp_SMTPSERVER = value
End Set
End Property
Public Property ServerPort() As Int32
Get
Return Temp_ServerPort
End Get
Set(ByVal value As Int32)
Temp_ServerPort = value
End Set
End Property
Public Sub New(ByVal GmailAccount As String, ByVal GmailPassword As String, Optional ByVal SMTPSERVER As String = "smtp.gmail.com", Optional ByVal ServerPort As Int32 = 587, Optional ByVal EnableSSl As Boolean = True)
Temp_GmailAccount = GmailAccount
Temp_GmailPassword = GmailPassword
Temp_SMTPSERVER = SMTPSERVER
Temp_ServerPort = ServerPort
Temp_EnableSSl = EnableSSl
End Sub
Public Function SendMail(ByVal ToAddressies As String(), ByVal Subject As String, ByVal BodyText As String, Optional ByVal AttachedFiles As String() = Nothing) As Boolean
Temp_ErrorText = ""
Dim Mail As New MailMessage
Dim SMTP As New SmtpClient(Temp_SMTPSERVER)
Mail.Subject = Subject
Mail.From = New MailAddress(Temp_GmailAccount)
SMTP.Credentials = New System.Net.NetworkCredential(Temp_GmailAccount, Temp_GmailPassword) '<-- Password Here
Mail.To.Clear()
For i As Int16 = 0 To ToAddressies.Length - 1
Mail.To.Add(ToAddressies(i))
Next i
Mail.Body = BodyText
Mail.Attachments.Clear()
If AttachedFiles IsNot Nothing Then
For i As Int16 = 0 To AttachedFiles.Length - 1
Mail.Attachments.Add(New Attachment(AttachedFiles(i)))
Next
End If
SMTP.EnableSsl = Temp_EnableSSl
SMTP.Port = Temp_ServerPort
Try
SMTP.Send(Mail)
Return True
Catch ex As Exception
Me.Temp_ErrorText = ex.Message.ToString
Return False
End Try
End Function
End Class
Its the way, how to use class:
Dim GGmail As New GGSMTP_GMAIL("MyFromAddress1#gmail.com", "AccPassword", )
Dim ToAddressies As String() = {"ToAddress1#gmail.com", "ToAddress2#gmail.com"}
Dim attachs() As String = {"d:\temp_Excell226.xlsx", "d:\temp_Excell224.xlsx", "d:\temp_Excell225.xlsx"}
Dim subject As String = "My TestSubject"
Dim body As String = "My text goes here ...."
Dim result As Boolean = GGmail.SendMail(ToAddressies, subject, body, attachs)
If result Then
MsgBox("mails sended successfully", MsgBoxStyle.Information)
Else
MsgBox(GGmail.ErrorText, MsgBoxStyle.Critical)
End If
Hope this helps. Good coding