How to send multiple emails with ASP.NET VB.net - asp.net

How do I set the code below to generate multiple emails like with a reminder every 15 minutes? Thank you for any guidance.
Private Sub SendEmail(ByVal pharmEmail As String, ByVal backupEmail As String)
Dim smtpClient As New System.Net.Mail.SmtpClient()
Dim message As New System.Net.Mail.MailMessage()
Try
Dim fromAddress As New System.Net.Mail.MailAddress(WebConfigurationManager.AppSettings("EmailFromAddr"), WebConfigurationManager.AppSettings("EmailFromName"))
message.From = fromAddress
message.To.Add(pharmEmail)
message.Subject = WebConfigurationManager.AppSettings("EmailSubject")
message.Priority = Net.Mail.MailPriority.High
If (WebConfigurationManager.AppSettings("backupEnabled") = True) Then
message.CC.Add(backupEmail)
End If
message.IsBodyHtml = True
Dim orderURL As New HyperLink
orderURL.Text = "here"
orderURL.NavigateUrl = "http://" & WebConfigurationManager.AppSettings("ServerName") & "/User/ReviewOrder.aspx?orderID=" & webOrderID
message.Body = "An order was created using the account of " + Profile.FirstName.ToString() + " " + Profile.LastName.ToString() + ". " + WebConfigurationManager.AppSettings("EmailBody") + "<a href='" + orderURL.NavigateUrl + "'>here.</a>"
'message.Body = WebConfigurationManager.AppSettings("EmailBody") & " " & orderURL.
smtpClient.Send(message)
Catch ex As Exception
ErrorHandler.WriteError(ex.ToString)
Throw ex
End Try

I agree with comments on the scheduler. If you don't like that you can create a windows service that does this. This will solve if you want to fire the routine every X minutes.
You don't have enough code here to send out emails, so you have to wrap this with some logic that fires the routine with the email information you want. More than likely, this is stored in a database (recipients, email) or some other persistent store.
I do caution the idea of sending reminders every 15 minutes to the same people, as you are more than likely to piss them off (unless that is your intent?).

Thank you all for you contributions. I have decided to create a SSIS package with a SQL and Send Email tasks. The SQL task check for new orders placed and the Send Email task sends reminder to users in a scheduled time.

Related

how to send an email using SendGrid V3 to multiple recipients, in a .NET app

It sends to one ok. But not to 2 or more. I've tried separating addresses by , and ; and space in the to_addr string, but failed.
What format does class EmailAddress expect for multiple addresses?
public async sub send_message( msg_subject, msg_body, from_addr_text, to_addr_text, optional commands = "")
dim apiKey = Environment.GetEnvironmentVariable("SENDGRID_API_KEY")
dim client as new SendGridClient( apiKey, , , "v3", )
dim from = new EmailAddress( from_addr_text, "INSTRUMENT")
dim subject = msg_subject
if subject = ""
subject = " " ' won't send if empty
End If
dim to_addr = new EmailAddress( to_addr_text, "INSTRUMENT")
dim plainTextContent = msg_body
dim htmlContent = "<strong>" & msg_body & "</strong>"
dim msg = MailHelper.CreateSingleEmail(from, to_addr, subject, plainTextContent, htmlContent)
dim response = await client.SendEmailAsync(msg)
if instr( commands, "SKIP POPUPS") ' TEST TEXT MSG !!!
exit sub
End If
popup_information( "MESSAGE SENDING", "Sent..." & vbcrlf & vbcrlf & "SUBJECT: " & vbcrlf & subject & vbcrlf & vbcrlf & "BODY: " & vbcrlf & msg_body )
end sub
Not sure which SDK version are you using , but if you follow the Sendgrid V3 api SDK for C# , you should find a method like below in the MailHelper class
public static SendGridMessage CreateSingleEmailToMultipleRecipients(EmailAddress from, List<EmailAddress> tos, string subject,string plainTextContent,string htmlContent)
which accepts a List<EmailAddress> to send email to multiple recipients. So instead of using the below line in your code
dim msg = MailHelper.CreateSingleEmail(from, to_addr, subject, plainTextContent, htmlContent)
you should use the below code
var to_addr = new List<EmailAddress>();
to_addr.Add(new EmailAddress( to_addr_text, "INSTRUMENT"));
to_addr.Add(new EmailAddress( "secondperson#test.com", "secondperson")); // you can add multiple email in this list
and then you can use to_addr in the code below
dim msg = MailHelper.CreateSingleEmailToMultipleRecipients(from, to_addr, subject, plainTextContent, htmlContent)
Pardon me for the example in C# but the same should be applicable for your VB.NET code
The stack overflow answer here shows how to implement SendGrid using dependency injection into a Net 6 Web API application using controllers.
The scenario of sending an email to multiple recipients is covered in the referenced example code here: https://github.com/Davidmendoza1987/dotnet-sendgrid-examples

paypal nvp .net sdk error

Folks,
We have a web site that uses PayPal Express Checkout for Digital Goods to make software sales. It has been working fine for 5 months. Last week we started getting an error "The request was aborted: Could not create SSL/TLS secure channel.” off the live site. When I run the site off my development server it runs fine and we can process a transaction. All these are against the live paypal site. In looking at many questions on this forum and others the main problem appears to be using the wrong endpoints. I am using the .NET SDK and the nvp methods. I checked the endpoints and they are the current ones provided by paypal for nvp transactions. Even looked in the dll to make sure we did't have an older version. We are good there.
Then I thought it might be that the hosting server could'd establish a secure link to paypal so created a test page with a url with query string to the endpoint like(https://api-3t.paypal.com/nvp?USER=XXXX_api1.XXX.com&PWD=XXX&SIGNATURE=XXXXXX&VERSION=60.0&PAYMENTACTION=Authorization&AMT=1.95&RETURNURL=https://www.paypal.com&CANCELURL=https://www.paypal.com&METHOD=SetExpressCheckout).
This worked and returned the expected transaction token. So we can connect from the hosting server. Then thinking our credentials or credential retrieval code might be the problem I pulled the credentials out of our database and ran the test as follows.
Test Query string with server data code======================================
This worked so credentials and endpoint are good on the hosting server.
( Dim sCEnvironment As String = System.Configuration.ConfigurationManager.AppSettings("Environment")
Dim dtsettings As DataTable
dtsettings = Dac.ExecuteDataTable("GetCredentials", Dac.Parameter("#Environment", sCEnvironment))
'// Set up your API credentials, PayPal end point, API operation and version.
Dim sAPIUsername As String = dtsettings.Rows(0).Item("UserName").ToString
Dim sAPISignature As String = dtsettings.Rows(0).Item("Signature").ToString
Dim sAPIPassword As String = dtsettings.Rows(0).Item("Password").ToString
Dim sEnvironment As String = dtsettings.Rows(0).Item("Environment").ToString
Dim QS As String = "https://api-3t.paypal.com/nvp?USER=" & sAPIUsername & "&PWD=" & sAPIPassword & "&SIGNATURE=" & sAPISignature & "&VERSION=60.0&PAYMENTACTION=Authorization&AMT=1.95&RETURNURL=https://www.paypal.com&CANCELURL=https://www.paypal.com&METHOD=SetExpressCheckout"
Response.Redirect(QS)
I then moved on to testing the token generation using the sdk dll (paypal_base.dll). See code below. As each line is generated I added to it a string that writes out to the test page so I can get an idea what is going on our hosting server. We use the express checkout for Digital Goods process. I got the basic code from https://cms.paypal.com/cms_content/FR/fr_FR/files/developer/nvp_DoAuthorization_cs.txt and added the Digital Goods query parameters per the online documentation. This works on my development server and returns the Token. It worked on the hosting site for about four months until sometime between January 27 and January 30 when I got the first notification that a customer could not purchase a product.
When run on our hosting server we get the “The request was aborted: Could not create SSL/TLS secure channel.” error message on the line of code highlighted below. The query string is generated by the encoder and held in the variable pStrrequestforNvp so the encoder works.
I am at a loss. What could be different on the hosting server than on our development server? Is there a method in the dll I could use to write out the actual call to the paypal server? I put the same dll file we used in development on the hosting site, but something is different.
Test the sdk generated query ===========================
Dim caller As NVPCallerServices = New NVPCallerServices
Dim profile As IAPIProfile = ProfileFactory.createSignatureAPIProfile
Dim sCEnvironment As String = System.Configuration.ConfigurationManager.AppSettings("Environment")
Dim dtsettings As DataTable
Dim sMsg As String
dtsettings = Dac.ExecuteDataTable("GetCredentials", Dac.Parameter("#Environment", sCEnvironment))
profile.APIUsername = dtsettings.Rows(0).Item("UserName").ToString
sMsg = "APIUserName = " & dtsettings.Rows(0).Item("UserName").ToString & "<br/>"
profile.APISignature = dtsettings.Rows(0).Item("Signature").ToString
sMsg = sMsg & "APISignature = " & dtsettings.Rows(0).Item("Signature").ToString & "<br/>"
profile.APIPassword = dtsettings.Rows(0).Item("Password").ToString
sMsg = sMsg & "APIPassword = " & dtsettings.Rows(0).Item("Password").ToString & "<br/>"
profile.Environment = dtsettings.Rows(0).Item("Environment").ToString
sMsg = sMsg & "Environment = " & dtsettings.Rows(0).Item("Environment").ToString & "<br/>"
caller.APIProfile = profile
Dim encoder As NVPCodec = New NVPCodec
encoder("VERSION") = "65.1"
encoder("METHOD") = "SetExpressCheckout"
encoder("RETURNURL") = "http://www.multiware.biz/return.aspx"
encoder("CANCELURL") = "http://www.multiware.biz/cancel.aspx"
encoder("PAYMENTREQUEST_0_CURRENCYCODE") = "USD"
encoder("PAYMENTREQUEST_0_PAYMENTACTION") = "Sale"
encoder("PAYMENTREQUEST_0_AMT") = "1.95"
encoder("PAYMENTREQUEST_0_ITEMAMT") = "1.95"
encoder("PAYMENTREQUEST_0_DESC") = "Software"
encoder("L_PAYMENTREQUEST_0_ITEMCATEGORY0") = "Digital"
encoder("L_PAYMENTREQUEST_0_NAME0") = "Test"
encoder("L_PAYMENTREQUEST_0_NUMBER0") = "123"
encoder("L_PAYMENTREQUEST_0_QTY0") = "1"
encoder("L_PAYMENTREQUEST_0_AMT0") = "1.95"
encoder("L_PAYMENTREQUEST_0_DESC0") = "Download"
encoder("REQCONFIRMSHIPPING") = "0"
encoder("NOSHIPPING") = "1"
encoder("SOLUTIONTYPE") = "Sole"
Try
Dim pStrrequestforNvp As String = encoder.Encode
sMsg = sMsg & "pStrrequestforNvp = " & pStrrequestforNvp & "<br/>"
Dim pStresponsenvp As String = caller.Call(pStrrequestforNvp) ***Error occurs here***
sMsg = sMsg & "pStresponsenvp = " & pStresponsenvp & "<br/>"
Dim decoder As NVPCodec = New NVPCodec
decoder.Decode(pStresponsenvp)
Dim Token As String = decoder("TOKEN")
sMsg = sMsg & "Token = " & Token & "<br/>"
Me.lblResponse.Text = sMsg.ToString
Catch ex As Exception
sMsg = sMsg & "<br/>" & ex.Message.ToString & "<br/>" _
& ex.StackTrace.ToString
Me.lblResponse.Text = sMsg.ToString
End Try
I'll answer my own question. After many back and forths with the web hosting service and PayPal we narrowed the problem to the Server not authorizing the Security Certificate. Had to put a trace on our page to find this and prove it was on their side. As I suspected it was an MS update that screwed things up. One day the site was working the next it wasn't.
For further reading on the subject see the dialog at http://forum.arvixe.com/smf/other-programs-promotions-graphics/need-urgent-help!-(paypal-checkout-not-working-any-more)/msg39498/#msg39498
To their credit the Arvixe folks tracked down the problem and eventually resolved it after we went back and forth a few times on whose problem it was.

Sending to external email fail

Here is the codes:
Dim SmtpServer As New SmtpClient()
Dim mail As New MailMessage()
Dim attachment As System.Net.Mail.Attachment
SmtpServer.Credentials = New _
Net.NetworkCredential("administrator#company.com", "1234")
SmtpServer.Port = 25
SmtpServer.Host = "SmtpServer"
mail = New MailMessage()
mail.From = New MailAddress("user#company.com.my")
mail.To.Add("recipient#external.com")
mail.CC.Add("user1#company.com")
mail.CC.Add("user2#company.com")
mail.Headers.Add("Disposition-Notification-To", "user1#company.com") 'Read receipt
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure 'Fail delivery notification
mail.Subject = "Sending Documents"
mail.Body = "To Whom May Concern," & vbCrLf _
& vbCrLf & "Please refer to the attachment for the documents." & vbCrLf & _
"NOTE : This is an automatically generated email and will be sent daily."
For Each path As String In attch
attachment = New System.Net.Mail.Attachment(path)
mail.Attachments.Add(attachment)
Next
Try
SmtpServer.Send(mail)
SmtpServer = Nothing
Catch ex As Exception
Response.Write(ex.ToString)
Exit Sub
End Try
Problem is only internal email receiving, not external email.
No errors shown during the code execution.
Any idea on how to solve this?
Or do I need to configure something at the Microsoft Exchange Server?
Also the server using the MailMarshal to do the filtering.
An advanced thanks for the contributing feedback.
Make sure that "mail.From" value is in the list allowed by SMTP server. It could be that relaying is not allowed.

smtp clients `SendAsync()` method

Protected Sub btnLocalSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLocalSubmit.Click
Dim logic = New connections
logic.emailsToSend(User.Identity.Name, getURL, reportedBy)
SendAsync()
Response.Redirect(getRedirectionPath, False)
Catch ex As Exception
Response.Write(ex.Message)
Finally
_con.Close()
_con.Dispose()
_sqlComm.Dispose()
End Try
End Sub
Sub SendAsync()
Dim _con As New SqlConnection(ConfigurationManager.ConnectionStrings("CitizenJDBConnectionString").ConnectionString)
Dim _sqlDataAdapter As New SqlDataAdapter("SELECT * FROM EmailSender", _con)
Dim _table As New System.Data.DataTable
Try
_con.Open()
_sqlDataAdapter.Fill(_table)
_con.Close()
For i As Integer = 0 To _table.Rows.Count - 1
Dim AppPath As String = Request.PhysicalApplicationPath
Dim sr As New StreamReader(AppPath & "EmailTemplates/NewReport.txt")
Dim message As New MailMessage()
message.IsBodyHtml = True
message.From = New MailAddress("admin#xxxx.com")
message.To.Add(New MailAddress(_table.Rows(i).Item(1)))
message.Subject = "New User registration !"
message.Body = sr.ReadToEnd()
sr.Close()
message.Body = message.Body.Replace("<%ReporterName%>", _table.Rows(i).Item(3))
message.Body = message.Body.Replace("<%ReportURL%>", _table.Rows(i).Item(2))
Dim client As New SmtpClient()
client.Host = "smtp.xxxxx.com"
'smtp.gmail.com
client.Port = 25
client.UseDefaultCredentials = True
client.Credentials = New System.Net.NetworkCredential("admin#xxxx.com", "123456")
'client.EnableSsl = True
Dim userState As Object = message
'wire up the event for when the Async send is completed
AddHandler client.SendCompleted, AddressOf SmtpClient_OnCompleted
client.SendAsync(message, userState)
Next
Catch ex As Exception
Response.Write(ex.Message)
End Try
End Sub 'SendAsync
Public Sub SmtpClient_OnCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
'Get the Original MailMessage object
Dim message As MailMessage = CType(e.UserState, MailMessage)
'write out the subject
Dim subject As String = message.Subject
If e.Cancelled Then
Console.WriteLine("Send canceled for mail with subject [{0}].", subject)
End If
If Not (e.Error Is Nothing) Then
Console.WriteLine("Error {1} occurred when sending mail [{0}] ", subject, e.Error.ToString())
Else
Console.WriteLine("Message [{0}] sent.", subject)
End If
End Sub 'SmtpClient_OnCompleted
I am using the smtp clients SendAsync() function to send out emails asynchronously...but this function does not work ...why?? i do not get any email..when i send it Synchronously...i get the emails, this means my settings are correct...so what is wrong with the SendAsync() method??
I do this all the time, and after years of doing this I suggest a (2) fold solution to your problem:
Refactor the actual sending email code (System.Net stuff) into a WCF service or separate .dll (I prefer the service).
Continue to use your asynchronous delegate call from your ASP.NET page but do so in a 'fire-and-forget' manner where you do not wire up any callbacks.
You might say you need to know if something went wrong with sending the email. Let the WCF service that sends the emails handle this. Do any logging in the service. After all that's all you were really doing anyways was logging. If you need to get fancier with a workflow if the email fails, there are ways that your ASP.NET can be flagged, but I think you will find that once the service to send the emails is stable, you will have very few problems.
In fact I have been doing this exact method for years using a service called by ASP.NET to send emails and have sent 10 of thousands of differing emails and never had any problem with this fire-and-forget design.
And lastly, setting the page Async=True makes the page act overall synchronously in the end by blocking the main thread until all asynchronous process are completed. This can make the pages very slow to load and is typically not desired.

Sharepoint not getting current user NetworkCredential from active directory

we have strange problem, we have single signon and we are trying to fetch unread email count from Exchange ews webservice, the problem is it always gets same count for all user which is actually for server user.
'it should now get for current user who requested the page
'but its always for server user where sharepoint is installed
Public Sub GetUnreadEmailCount()
Dim errormsg As String = String.Empty
Dim UnreadCount As Integer = 0
Dim esb As New ExchangeServiceBinding
Try
esb.RequestServerVersionValue = New RequestServerVersion
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1
esb.UseDefaultCredentials = True
esb.Url = Domain + "/EWS/Exchange.asmx"
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf CertificateValidationCallBack)
Dim biArray(1) As BaseFolderIdType
Dim dfFolder As New DistinguishedFolderIdType
dfFolder.Id = DistinguishedFolderIdNameType.inbox
biArray(0) = dfFolder
Dim geGetFolder As New GetFolderType
geGetFolder.FolderIds = biArray
geGetFolder.FolderShape = New FolderResponseShapeType
geGetFolder.FolderShape.BaseShape = DefaultShapeNamesType.AllProperties
Dim gfResponse As GetFolderResponseType = esb.GetFolder(geGetFolder)
Dim rmta As ResponseMessageType() = gfResponse.ResponseMessages.Items
Dim rmt As FolderInfoResponseMessageType = DirectCast(rmta(0), FolderInfoResponseMessageType)
If rmt.ResponseClass = ResponseClassType.Success Then
Dim folder As FolderType = DirectCast(rmt.Folders(0), FolderType)
UnreadCount = folder.UnreadCount
End If
Label1.Text = vbCrLf + "Unread email count : " + UnreadCount.ToString
' Return UnreadCount
Catch ex As Exception
If Not ex.Message Is Nothing Then errormsg = ex.Message
Try
If Not ex.InnerException.Message Is Nothing Then errormsg = errormsg + " : " + ex.InnerException.Message
Catch e As Exception
End Try
Finally
If esb IsNot Nothing Then esb.Dispose() : esb = Nothing
If Not errormsg = String.Empty Then
Label1.Text = vbCrLf + "Error : " + errormsg
End If
End Try
End Sub
We were actually having the same problem, although we were not using single sign on. So I'm not sure this is exactly what you are experiencing.
The problem is that you can not have a user on Machine A give their credentials to Machine B (SharePoint?) and then have Machine B send those credentials on to Machine C
It's referred to as the "Double Hop" problem and is a security feature, however I'm not really into the technical side of it. Our solution was to use Kerberos.
I hope this helps you, if not, that it helps you rule out this specific issue :)
Your server side code is running as the AppPool's identity, which is your sharepoint service account. I'm assuming that's what you mean by 'the server user.'
esb.UseDefaultCredentials = true;
will use the creds of the context. I'm not sure of what's available in the EWS services, so if you can use a higher-privileged account and get based on the user coming in, i.e., HttpContext.Current.User.Identity as a parameter, then that may be the best way.
You could authenticate via javascript directly to the EWS services, skipping server-side code altogether, and write something that consumes & displays the server stuff as you need it.
You'd need to find a way to auth the user directly to the EWS services. Double-hop is an issue with NTLM, as your NTLM ticket is only valid for the first hop. Kerberos fixes that, but you still need to impersonate.

Resources