Sending email with embedded images using Sendgrid on Azure - asp.net

I have an ASP.NET website published to Azure from which emails can be sent. Some are plain text but I added a welcome email that is newsletter style with embedded images. The code is VB.NET. I have the system working nicely on our development server displaying a preview before sending the email. On Azure, the code to send the newsletter email is not working. The plain text email goes OK and I have tested the newsletter as an HTML email without the embedded images and that goes through OK. The preview can find the images so I am sure they are there and can be accessed. I do not get any error message, the email just never shows up in the sendgrid account as being processed. The code is as follows:
Try
Dim mymessage = New SendGridMessage
mymessage.From = New MailAddress("do-not-reply#company.co.uk")
mymessage.AddTo(txtemail.Text)
mymessage.Subject = "Welcome Email"
mymessage.Text = plaintext
mymessage.Html = htmlBody
Dim arrct As Integer = arrImages.Count - 1
For i As Integer = 0 To arrct
mymessage.AddAttachment(arrImages(i).ipath)
mymessage.EmbedImage(arrImages(i).fname, arrImages(i).id)
Next
Dim username = ConfigurationManager.AppSettings("emailServiceUserName")
Dim pswd = ConfigurationManager.AppSettings("emailServicePassword")
Dim credentials = New NetworkCredential(username, pswd)
Dim transportweb = New Web(credentials)
transportweb.DeliverAsync(mymessage)
'code here to display success message
Catch exc As Exception
'error code here
End Try
The array of images is populated with a number of images located in a folder as they don't change, like so:
Dim research As String = Server.MapPath("~\ImageTemp\" + query.ImageName)
'Extend the array
ReDim Preserve arrImages(i + 1)
arrImages(i + 1).ipath = respath
arrImages(i + 1).fname = qry.ImageName
arrImages(i + 1).id = "img" & i + 1
I have checked the web and can find others who have problems where the code works on the local server but not on Azure but no answers that help with this specific questions. It must be to do with the way I am handling the images but I can't see it.
Have reviewed
Unable to send emails on Azure Web App using Sendgrid
How to send embedded images with sendgrid emails?
Sending an email with attachment using SendGrid

The answer is to change the addattachment code to this :
Dim arrct As Integer = arrImages.Count - 1
For i As Integer = 0 To arrct
mymessage.AddAttachment(Server.Mappath("~\ImageTemp\" & arrImages(i).fname)
mymessage.EmbedImage(arrImages(i).fname, arrImages(i).id)
Next

Related

sending email with attachment from Azure using SendGrid

How do I send an email with an attachment using SendGrid, from my VM in Azure?
I added myMsg.AddAttachment and supplied the parameters. I get no errors when I execute, but Email never gets sent. If I comment out this line,
email gets sent.
What am I doing wrong? This is in ASP.net VB.
I used Sendgrid 9.9.0 to check this issue, here is the code snippet:
'instantiate the SendGridMessage object
Dim sendGridMessage = New SendGridMessage()
sendGridMessage.From = New EmailAddress("xxxxxx#hotmail.com", "BruceChen1019")
sendGridMessage.AddTo(New EmailAddress("xxxxx#gmail.com", "Bruce Chen"))
sendGridMessage.PlainTextContent = "Hello World!"
sendGridMessage.Subject = "Hello Email!"
'instantiate the Attachment object
Dim attachment = New Attachment()
attachment.Filename = "helloword.txt"
attachment.Content = Convert.ToBase64String(Encoding.UTF8.GetBytes("hello world!!!"))
attachment.Type = "text/plain"
Dim attachments = New List(Of Attachment)
attachments.Add(attachment)
sendGridMessage.AddAttachments(attachments)
'send the email
Dim Response = client.SendEmailAsync(sendGridMessage).Result
Console.WriteLine(Response.StatusCode) //202 Accepted
Console.ReadLine()
TEST:
Moreover, for your attachment file, you need to set the correct MIME Type for attachment.Type based on the file extension, and Base64 encode your file content.
Also, you need to follow the Attachments limitations. And you may follow evilSnobu's comment about going to SendGrid portal for troubleshooting this issue.

Prevent LinkedResource image getting added as attachment

On a page that sends emails using System.Net.Mail I have this to embed an image into a html formatted email.
string logoPath = "W:\\WebSites\\logo.jpg";
LinkedResource imagelink = new LinkedResource(logoPath, "image/jpg");
imagelink.ContentId = "imageId";
imagelink.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(MessageHeader + Message.ToString() + MessageFooter, null, "text/html");
htmlView.LinkedResources.Add(imagelink);
In the code that creates the email, the image is embedded like this.
MessageHeader += "<img alt=\"Company Logo\" hspace=0 src=\"cid:imageId\" align=baseline border=0>";
This all works okay. The logo appears in the html formatted email where it should be. But, when users receive the email there is also an attached image - in Outlook you see an attachment always called ATT00001 - which, if you download, is the logo image.
How can I prevent the logo getting added as an attachment as well as being embedded? It looks unprofessional to have the logo in the message but also attached waiting to be downloaded. Users complain they think there is an attachment - but in fact it is just the logo.
I figured out the solution for this question. When you add the LinkedResource object, you have to define the correct MIME type, and if you do so, the email client won't offer the embedded images as attachments.
Here is a sample code grabbed from my scenario (vb.net code):
'Your email
Dim _htmlSource As New StringBuilder("<html> ... YOUR HTML EMAIL ... </html>")
Dim _linkedResources As New List(Of LinkedResource)
Dim _href As String = "http://your.image.url/image.png"
'Adding images
Dim _imageStream As MemoryStream
Dim _mimeType As String
Using _wc = New WebClient
_imageStream = New MemoryStream(_wc.DownloadData(_href))
_mimeType = _wc.ResponseHeaders("content-type")
End Using
Dim _contentId As String = Guid.NewGuid.ToString
_htmlSource.Replace(_href, "cid:" & _contentId)
_linkedResources.Add(New LinkedResource(_imageStream, New ContentType(_mimeType)) With {.ContentId = _contentId})
'Compile mail message
Dim mail As New MailMessage
mail.IsBodyHtml = True
Dim _htmlView As AlternateView = AlternateView.CreateAlternateViewFromString(_htmlSource.ToString(), Nothing, MediaTypeNames.Text.Html)
_htmlView.TransferEncoding = TransferEncoding.EightBit
_linkedResources.ForEach(Sub(lr) _htmlView.LinkedResources.Add(lr))

WooCommerce REST API The remote server returned an error: (401) Unauthorized VB.NET

My site (https://www.trs.is) recently switched to https and now I am getting an Unauthorized error when I try to get all products from my WooCommerce store. I have tried many things with the WebClient() to use basic authentication but I always get this error.
I have also tested this with Postman from Google with basic auth and using the client key and client secret but the error is always the same.
Scratching my head here and after hours of searching I can not see why the this is happening.
Here is my latest code (actual client keys are removed)
Dim url As String = "https://www.trs.is/wc-api/v3/products"
'Dim client As New WebClient()
Dim userName As [String] = "myclientkey"
Dim passWord As [String] = "myclientsecret"
'client.Credentials = New System.Net.NetworkCredential(userName, passWord)
Dim credentials As String = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord))
wc.Headers(HttpRequestHeader.Authorization) = Convert.ToString("Basic") & credentials
Dim result = wc.DownloadString(url)
Any help guys ?
Try using wc.UseDefaultCredentials = True and post your API keys instead.

ASP email script

I have a form that I validate that data with, and what I'm wondering is, do I need to sanitize the data JUST to send an email? The email will be sent to a predefined email address. Basically the form just ask for a name, email (of the person using the form), and a url.
Then this gets sent to the predefined email address. IS something like this safe enough to use? Is it vulnerable to use a simple ASP page like this:
<%
dim objMessage
dim FullName
FullName=Request.QueryString("name")
dim email
email=Request.QueryString("email")
dim videourl
videourl=Request.QueryString("video")
dim txtMessage
txtMessage="<b><br><br>Name: " & FullName & "<br>Email: " & email & "<br><br>Video URL: " & videourl
objMessage = CreateObject("CDO.Message")
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "localhost"
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objMessage.Configuration.Fields.Update
objMessage.Subject = "qContest Submission"
objMessage.From = email
objMessage.To = "predefined#email.org"
objMessage.HTMLBody = txtMessage
objMessage.Send
%>
NOTE: This is NOT using any database or anything like that...
Also this script is being called via AJAX, if that matters...
always use Server.HTMLEncode when showig user-posted data in HTML. In this case you put it in the HTMLBody of the email, so I would definitely HTMLEncode:
FullName = Server.HTMLEncode(Request.QueryString("name"))
etc. This avoids the possibility to post vulnerable things like Javascript as that could be executed when opening the email.

Exception thrown when using GData .NET Analytics API

I am facing an issue while trying to fetch data from GoogleAnalytics API on piece of code that has been working well just a couple of days ago.
For this I am referencing the following DLL's:
Google.GData.Analytics.dll
Google.GData.Client.dll
Google.GData.Extensions.dll
And I am using the following code:
Dim visits As String = String.Empty
Dim username As String = "myuser#mydomain.com"
Dim pass As String = "mypassword"
Const dataFeedUrl As String = "https://www.google.com/analytics/feeds/data"
Dim query As AccountQuery = New AccountQuery()
Dim service As AnalyticsService = New AnalyticsService("MyWebAnalyticsService")
service.setUserCredentials(username, pass)
Dim accountFeed As AccountFeed = service.Query(query) ''----------> Exception thrown in this line: GDataRequestException Execution of request failed: https://www.google.com/analytics/feeds/accounts/default
I thought it had to do with a blocking to the account I was using but it wasn't the case because I verified registering the site for another analytics account and is still not working.
This code has been working flawlessly as I've said but all of a sudden has stopped doing so yesterday.
Could you please help me figuring out what's wrong?. Maybe the way the user credentials are set has changed and I am missing something.
Thank you very much for your help.
'----Update----
I managed to make it work and now I can query the visits for a desired domain. The code goes as follows:
Dim visits As String = String.Empty
Dim username As String = "myuser#mydomain.com"
Dim pass As String = "mypassword"
'Follow the instructions on https://developers.google.com/analytics/resources/articles/gdata-migration-guide (Create a Project in the Google APIs Console) to generate your key
'Once you have it set it as part of the querystring to request our GA service
Dim gkey As String = "key=yourkeystring"
'Set the new URI to retrieve the feed data and append it the generated key
Dim dataFeedUrl As String = "https://www.google.com/analytics/feeds/data?" & gkey
'Create and authenticate on our service instance
Dim service As AnalyticsService = New AnalyticsService("MyAnaliticsService")
service.setUserCredentials(username, pass)
'Use the profile id for the account you want to get ths visits from, you can find it
'logging in your analytics account, select the desired domain on your list (blue link)
click on the administrator button and on the profiles tab find the profile
'configuration subtab, right there you will find the profile id in this case the eight characters long id 12345678
Dim query1 As DataQuery = New DataQuery(dataFeedUrl)
With query1
.Ids = "ga:12345678"
.Metrics = "ga:visits"
.Sort = "ga:visits"
.GAStartDate = DateTime.Now.AddMonths(-1).AddDays(-2).ToString("yyyy-MM-dd")
.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd")
.StartIndex = 1
End With
'Use the generated datafeed based on the former query to get the visits
Dim dataFeedVisits As DataFeed = service.Query(query1)
For Each entry As DataEntry In dataFeedVisits.Entries
Dim st As String = entry.Title.Text
Dim ss As String = entry.Metrics(0).Value
visits = ss
Next
I have the same problem and it looks like google recently shut down the feed. It is answered in another post. Issue com.google.gdata.util.ResourceNotFoundException: Not Found with Google Analytic
Please make sure you registered your project in the APIs Console and you are sending the API Key with your requests.
If that is not the issue, inspecting the inner exception will give you more details about the error. As an alternative, you can use Fiddler to capture the HTTP request and the response. The latter will include a more descriptive error message.

Resources