Dim x As String
x = "http://www.domain.com/aaa/test/default2.aspx?date=" & now.Text & "&tfname=" & p1fname.Text & "&tlname=" & p1lname.Text & "&comp=" & Request.QueryString("comp")
Dim objEmail As New MailMessage()
objEmail.To = "test#email.com"
objEmail.From = "me#test.com"
objEmail.Cc = "test#email.com"
objEmail.Subject = "Test Email"
objEmail.Body = x
SmtpMail.SmtpServer = "mail.domain.com"
Try
SmtpMail.Send(objEmail)
Catch exc As Exception
Response.Write("Send failure: " + exc.ToString())
End Try
When I get the email it comes with
http://www.domain.com/aaa/test/default2.aspx?date=1/13/2011
as a link
and the rest as text
11:39:09 AM&tfname=sadasd&tlname=asd&comp=GWI
Whenever you put a parameter into a query string, you should encode it using System.Web.HttpUtility.UrlEncode to avoid invalid characters going into the URL:
x = "http://www.domain.com/aaa/test/default2.aspx?date=" & HttpUtility.UrlEncode(now.Text) &
"&tfname=" & HttpUtility.UrlEncode(p1fname.Text) &
"&tlname=" & HttpUtility.UrlEncode(p1lname.Text) &
"&comp=" & HttpUtility.UrlEncode(Request.QueryString("comp"))
You cannot have Spaces in the query string, if you need to put spaces, replace it with %20 before appending to the querystring. Although the ideal way to do this is to encrypt and decrpt the text in the querystring.
Related
I have this email sending function:
''' <summary>
''' Sends an email.
''' </summary>
''' <param name="from">Who is the email coming from?</param>
''' <param name="to">Who is the email going to?</param>
''' <param name="subject">Subject of the email.</param>
''' <param name="body">Body text of the email.</param>
''' <returns>true if an email was sent, false if sending failed.</returns>
Public Shared Function SendEmail(ByVal from As String, ByVal [to] As String, ByVal subject As String, ByVal body As String) As Boolean
' sanity check - can't send to nobody!
If String.IsNullOrWhiteSpace([to])
Return False
End If
' get http objects
Dim http = HttpContext.Current
Dim Request = http.Request
Dim Session = http.Session
Dim Response = http.Response
' find SMTP server
Dim smtpServer As String
If Request.ServerVariables("SERVER_NAME") = OverridableServerName Then
smtpServer = LocalServerName
Else
smtpServer = Request.ServerVariables("SERVER_NAME")
End If
' compose email
Try
Dim message As New MailMessage(from, [to], subject, body.Replace(vbCrLf, "<br/>"))
message.IsBodyHtml = True
Dim emailClient As New SmtpClient(smtpServer)
emailClient.Send(message)
Return True
Catch ex As Exception
Dim uri = New Uri(Request.Url.PathAndQuery, UriKind.Relative).ToString()
' trim off the query string
If (uri.IndexOf("?") >= 0)
uri = uri.Substring(0, uri.IndexOf("?"))
End If
Response.Redirect("ErrorPage.asp?ErrorMsg=From " & uri & "<br><br>" & smtpServer & "<br>" & from & "<br>" & [to] & "<br>" & subject & "<br>" & Replace(body, vbCrLf, "<br>") & "<br>" & Replace(ex.Message, vbCrLf, "<br>"))
Return False
End Try
End Function
The problem is that even though I am setting the IsBodyHtml flag to true, the <br/> tags that I am replacing newlines with get rendered literally rather than as newlines in the resulting email. is there a better way to do this? Should I not replace the newlines with <br/> tags? (I would test it out but I don't have a local email server, which is why I'm asking what to do here, so I don't have to keep throwing it over the fence into testing land just to see the resulting emails...)
message.IsBodyHtml = True did actually fix it, even though I thought it didn't; we were just testing the wrong system when thinking it wasn't fixed. Oops!
I am not able to make an authenticated call against Cybersource api and apitest environments, even though my signature routine is able to generate the correct signature from their test page.
I tried different headers combination, upper and lower case, and date vs v-c-date field names.
I constructed the signature from the following headers components.
'VB, Signature Construction
Dim pHost As String = "host: apitest.cybersource.com"
Dim pMerc As String = "v-c-merchant-id: testmid"
Dim pDate As String = "v-c-date: " & Now.ToUniversalTime.ToString("r")
Dim pReq As String = "(request-target): get /reporting/v3/report-downloads?organizationId=testmid&reportDate=2018-10-27&reportName=Demo_Report"
Dim pHeader As String = pHost & Chr(10) & pDate & Chr(10) & pReq & Chr(10) & pMerc
Dim kID As String = "{secret key}"
Dim mSig As String = GenerateSignatureFromParams(pHeader, kID)
Dim pSig As String = "signature: keyid=""{key id}"", algorithm=""HmacSHA256"", headers=""host v-c-date (request-target) v-c-merchant-id"", signature=""" & mSig & """"
When added the host, v-c-merchant-id, v-c-date, and signature to the request header for a GET, I received a response of (401) Unauthorized.
The header names are:
$headerString = "host date (request-target) v-c-merchant-id"
appears your name "v-c-date" should be "date"
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
It seems I'm not lucky with backslashes in ASP.Net VB.Net.
I'm trying to output some infos about files with ffprobe and my paths are cut randomly at some backslash in every string containing backslash.
I debugged this function to return the path generated by fileToProcess:
Function ffprobe_show_format(ByVal arg As String) As String
Dim myProcess As New System.Diagnostics.Process()
Dim fileToProcess As String = MapPath(".") & "\temps\" & arg
myProcess.StartInfo.FileName = MapPath(".") & "\ffprobe.exe"
myProcess.StartInfo.Arguments = "-show_format " & fileToProcess & " >C:\inetpub\vhosts\mysite.com\httpdocs\absolutefs\ffmpegtemp.txt"
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.RedirectStandardInput = True
myProcess.StartInfo.RedirectStandardOutput = True
myProcess.Start()
Dim myStreamWriter As StreamWriter = myProcess.StandardInput
Dim mystreamreader As StreamReader = myProcess.StandardOutput
Dim str As String = mystreamreader.ReadToEnd
Return str & ";" & "FileToProcess=" & fileToProcess & "MapPath(.) AND ffprobe.exe" & MapPath(".") & "\\ffprobe.exe"
End Function
And it returns ;FileToProcess=C:
It means that
My file is not processed because of some errors
My Path is cut at backslashes
The rest of the string is then broken
Does I need to tell asp.net to represent backslashes in another way?
[EDIT]
I can't choose an answer but will upvote since I made two mistakes:
- To debug, I was reading my value once it was put in SQL variables with limites size then
- ... fetched with Newtonsoft.Json parser that probably was refusing some chars.
I'm new on ASP.Net so I have difficulties finding a good way to debug. So I finally made as usual when I'm not able to debug on a platform: I've written my debug vars in a text file, and everything was there using this way:
Function ffprobe_show_format(ByVal file As String, ByVal app As String) As String
Dim myProcess As New System.Diagnostics.Process()
myProcess.StartInfo.FileName = app
Dim argz As String = FormatCommandLine("-show_format", file)
myProcess.StartInfo.Arguments = argz
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.RedirectStandardOutput = True
myProcess.Start()
Dim mystreamreader As StreamReader = myProcess.StandardOutput str As String = mystreamreader.ReadToEnd
MapPath(".") & "/ffprobe.exe"
Dim objWriter As New System.IO.StreamWriter(MapPath(".") & "\debug.txt")
objWriter.Write(str)
objWriter.Close()
Return str
End Function
I'll add an ffmpeg tag since it's also another example on how to call it and process a file.
You don't need to worry about the backslashes. The backslash is not a special character in VB like it is in C#. In fact if you do double them up you might hit errors.
It's hard to tell where the problem is occurring. Some ideas to try to narrow it down:
Try not redirecting StandardInput since you aren't passing it anything.
Read from StandardError to make sure it is empty. It may contain an error message.
I would make use of Debug.WriteLine to trace the function and try to spot where things begin to go wrong.
This may not matter, but I would place myProcess.WaitForExit after mystreamreader.ReadToEnd.
Larry's suggestion to use System.IO.Path is a good one.
Some hastily modified code based on all this:
Function ffprobe_show_format(ByVal arg As String) As String
Debug.WriteLine("arg: " & arg)
Dim fileToProcess As String = IO.Path.Combine(MapPath("."), "temps\" & arg)
Debug.WriteLine("fileToProcess = " & fileToProcess)
Debug.WriteLine("MapPath AND ffprobe.exe: " & IO.Path.Combine(MapPath(".") & "\\ffprobe.exe"))
Dim myProcess As New System.Diagnostics.Process()
myProcess.StartInfo.FileName = IO.Path.Combine(MapPath("."), "\ffprobe.exe")
myProcess.StartInfo.Arguments = "-show_format " & fileToProcess & " >C:\inetpub\vhosts\mysite.com\httpdocs\absolutefs\ffmpegtemp.txt"
myProcess.StartInfo.UseShellExecute = False
'myProcess.StartInfo.RedirectStandardOutput = True
myProcess.StartInfo.RedirectStandardError = True
myProcess.Start()
'Dim str As String = myProcess.StandardOutput.ReadToEnd
Dim errStr as string = myProcess.StandardError.ReadToEnd
myProcess.WaitForExit()
Debug.WriteLine("myProcess exit code = " & myProcess.ExitCode.ToString())
'Debug.WriteLine("stdOutput: " & str)
Debug.WriteLine("stdError: " & errStr)
Return str & ";" & "FileToProcess=" & fileToProcess
End Function
There are a few things to consider here.
First, the back-slash character is the escape character (i.e. \t \n \r ...) and should be double-escaped \\ IF you MUST embed it into strings.
However, the .NET framework contains a very good class: System.IO.Path that has several Combine method overloads that can help you to construct paths without embedding back-slash characters into strings. This also makes your code more portable in the (somewhat unlikely) event that you would ever run it on a non-Windows platform.
http://msdn.microsoft.com/en-us/library/system.io.path
Try closing the StreamReader before accessing its contents:
Dim myStreamReader As StreamReader = myProcess.StandardOutput
Dim str As String = myStreamReader.ReadToEnd
myStreamReader.Close()
Return str & ";" & "FileToProcess=" & fileToProcess & "MapPath(.) AND ffprobe.exe" & MapPath(".") & "\\ffprobe.exe"
When I run your function in my local devbox:
Function ffprobe_show_format(ByVal arg As String) As String
Dim myProcess As New System.Diagnostics.Process()
Dim fileToProcess As String = HttpContext.Current.Server.MapPath(".") & "\temps\" & arg
myProcess.StartInfo.FileName = HttpContext.Current.Server.MapPath(".") & "\ffprobe.exe"
myProcess.StartInfo.Arguments = "-show_format " & fileToProcess & " >C:\inetpub\vhosts\mysite.com\httpdocs\absolutefs\ffmpegtemp.txt"
'myProcess.StartInfo.UseShellExecute = False
'myProcess.StartInfo.RedirectStandardInput = True
'myProcess.StartInfo.RedirectStandardOutput = True
'myProcess.Start()
'Dim myStreamWriter As StreamWriter = myProcess.StandardInput
'Dim myStreamReader As StreamReader = myProcess.StandardOutput
Dim str As String = String.Empty 'myStreamReader.ReadToEnd
Return str & ";" & "FileToProcess=" & fileToProcess & "MapPath(.) AND ffprobe.exe" & HttpContext.Current.Server.MapPath(".") & "\\ffprobe.exe"
End Function
I get what I consider to be a somewhat normal string returned for ffprobe_show_format:
";FileToProcess=C:\Documents and Settings\Me\My Documents\Proj1\SubApp1\temps\testMapPath(.) AND ffprobe.exeC:\Documents and Settings\Me\My Documents\Proj1\SubApp1\\"
I commented out the System.Diagnostics.Process() as I don't have an executable called ffprobe.exe.
Given that the rest of it works, Try closing the StreamReader before accessing its contents.
You should just need to escape each backslash with another backslash.
Or, you might be able to prefix your string with the # symbol (works in C#, not sure about VB.NET).
I.E.
instead of "C:\this\that.exe"
use "C:\this\that.exe"
or #"C:\this\that.exe"
Previous question which links onto this and has any addition code ref should I forget to link any, I have set it up to email me should someone submit this form and an error occur and right now should that occur for most integer or datetime fields if they fail to validate then it will show me which fields in the email failed and what was input into them.
Problem I'm having now is to validate the drop downs and the textboxs in a similar way to what I with integer and datetime fields so I can display those also in the email in case they error.
present integer and datetime validation
Catch ex As Exception
lblInformation.Text = ("<h4>Unable to save data in database</h4>" + vbNewLine + "The error was '" + ex.Message + "'" + vbNewLine + vbNewLine + vbNewLine + "The SQL Command which falied was:" + vbNewLine + "<strong>" + mySQL + "</strong>" + vbNewLine).Replace(vbNewLine, "<br />" + vbNewLine)
Dim dtb As DateTime
If Not DateTime.TryParse(DateOfBirth, dtb) Then
strEMessageBody.Append("<strong>Date Of Birth:</strong> " & DateOfBirthYear.SelectedItem.Value & "-" & DateOfBirthMonth.SelectedItem.Value & "-" & DateOfBirthDay.SelectedItem.Value & vbCrLf)
strEMessageBody.Append("<br/>" & vbTab & vbTab & vbTab & vbTab & vbTab & vbTab)
End If
Dim iao As Integer
If Not Integer.TryParse(AnyOther, iao) Then
strEMessageBody.Append("<strong>Any Other:</strong> " & rblAnyOther.Text & vbCrLf)
strEMessageBody.Append("<br/>" & vbTab & vbTab & vbTab & vbTab & vbTab & vbTab)
End If
then below the final validation I have the Dim for the email setting but that I sorted out in the other question.
The problem is much earlier in the page I have
Sub Upload_Click(ByVal source As Object, ByVal e As EventArgs)
If (Page.IsValid) Then
Dim Name As String
Which prevents me just using there names as shown above where I would instead call them something else but that doesn't work with strings so my main issue is having some bit of code to check if the strings are valid and for the dropdowns which would either work but always show the data in the email or would hiccup in the code,
Dim imd As Integer
If Not Integer.TryParse(dept, imd) Then
strEMessageBody.Append("<strong>Department:</strong> " & dept.Text & vbCrLf)
strEMessageBody.Append("<br/>" & vbTab & vbTab & vbTab & vbTab & vbTab & vbTab)
End If
below was how it had been setup to record the department
Department = dept.SelectedItem.Value
Department = Replace(Department, "'", "''")
Summary:- Need vb code to validate if strings and dropdowns are valid and the use of try/catch block is another possible solution but I wasn't able to figure out how to implement validation for that either.
Log your values into your database. Setup a logging table called "tblLog" or something else. Record the value of ex.Message or possibly even InnerException (if it exists).
Going hand in hand with Matt's answer, there is a tool that can help you with automatically logging errors to a DB.
It's called ELMAH.
EDIT
Here are 2 validations that you might want to use:
Dim s As String = "some user input in here"
If [String].IsNullOrEmpty(s) Then
' Watch out, string is null or it is an empty string
End If
Dim cb As New ComboBox()
If cb.SelectedItem Is Nothing Then
' Watch out, combo has no item selected
End If
NOTE ComboBox is a WinForm control in this example, but the idea is the same for the ASP.NET counterpart
Since everybodies given up trying to find a solution then I'm just gona close this topic with this post as the answer.