System.Net.Mail.MailAddress allows commas in email address? - asp.net

Recently, I updated some code to use System.Net.Mail.MailAddress() to check if an e-mail address is valid or not. Shortly after, I noticed some email addresses with commas in the domain name are considered valid, for example, the code below will indicate the email address is Valid???
Good grief! -- how are the rest of you handling this??
dim ok as Boolean
dim test_str as String = "someone#comma,com"
dim email as System.Net.Mail.MailAddress
ok = true
Try
email = new System.Net.Mail.MailAddress( test_str )
Catch ex As Exception
ok = false
End Try
if ( ok ) then
response.write( "Valid" )
else
response.write( "INVALID" )
end if

Related

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.

Why does my if else return false?

In my Appcode folder as seen above I have a Class called BaseClass. In BaseClass I have a function called CheckWAN() that defines IP ranges so that later I can auto authenticate local users to my site via their IP address range.
Public Function CheckWAN() As Boolean
Try
Dim url As String = Request.Url.ToString()
'Get the client ip address
Dim RemoteAddress As String = Request.UserHostAddress
Dim strRemoteAddress As String = RemoteAddress
Dim myWAN As String = "192.168.254.254"
'add Some other ips
Dim SOther001 As String = "192.168.254.1"
Dim SOther002 As String = "192.168.254.2"
Dim SOther003 As String = "192.168.254.3"
If strRemoteAddress.Contains(myWAN) Then
Return True
ElseIf strRemoteAddress.Contains(SOther001) Then
Return True
ElseIf strRemoteAddress.Contains(SOther002) Then
Return True
ElseIf strRemoteAddress.Contains(SOther003) Then
Return True
Else
Return False
End If
Catch
Return False
End Try
End Function
Finally I have a set up a login on the site default.aspx that Checks the IP address of the user connecting if the If CheckWAN() returns true then I get passed along to the content page however if it is false then it shows me the login with a message that it is returning false
Public Class BaseClass
Inherits System.Web.UI.Page
If CheckWAN() = True Then
Response.Redirect("/content.aspx")
Else
Response.Write("The CheckWAN is returning False")
'this else also causes a redirect loop if its changed to
'Response.Write(/default.aspx) not sure why
End If
I have also checked with networking to verify the IP's used in my code and they all are valid.
Edited!
here is what Request.UserHostAdress returns
debug
First of all, this should not even compile. Apparently it does, so you must have Option Strict Off. Request.UserHostAdress returns a complex object, and you declared your variable as a string. I suspect that what you actually want is some property of that object, although I don't know which one.

Validate ASP.NET membership Username and Password when IsApproved is false

How can I check if the password entered by the user matches the password stored in the database when the IsApproved value is FALSE?
What I hope to do is as follows...
User registers - details saved and IsApproved is set to false
User recieves welcome email with membership confiirmation link
User clicks link in email - IsApproved is set to True at this point
User can NOW login
Okay everyting is fine with all of the above and i dont percieve any problems.
Where I'm having issues is...
When the user attempts to login and his/her IsApproved flag is FALSE
I need to cross reference his/her password wih the one stored in DB
And thats where i'm stuck.
The idea was to cross check the password, and if the user entered VALID credentials then to show a message to the user to say ACTIVATE your membership by clicking in the email blah blah blah.
But even if the password entered matches, because I cannot check it in the code the ValidateUser function always returns false because IsApproved is set to false!
Can anyone point me in the right direction please?
ALSO I dont actually need to see the password, so even if theres a sealed function I can call that simply confirms if the pasword matches thats fine too...
Below is my code block..
Public Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef PwdMatches As Boolean, ByRef Approved As Boolean) As Boolean Implements IMembershipService.ValidateUser
'
Dim ThisMember As MembershipUser = Nothing
Dim ThisResult As Boolean = Nothing
'
Approved = False
ThisResult = False
PwdMatches = False
If String.IsNullOrEmpty(Username) Then
Throw New ArgumentException("Value cannot be null or empty.", "Username")
ElseIf String.IsNullOrEmpty(Password) Then
Throw New ArgumentException("Value cannot be null or empty.", "Password")
ElseIf _Provider.ValidateUser(Username, Password) Then
ThisResult = True
Else
Try
ThisMember = _Provider.GetUser(Username, False)
Try
If (ThisMember Is Nothing) = False Then
Approved = ThisMember.IsApproved
Try
<!-- This is the point im stuck on -->
If Password_Matches_With_Password_In_Db Then
PwdMatches = True
Else
PwdMatches = False
End If
Catch ex As Exception
ThisResult = False
End Try
Else
ThisResult = False
End If
Catch ex As Exception
ThisResult = False
End Try
Catch ex As Exception
ThisResult = False
End Try
End If
Return ThisResult
ThisMember = Nothing
ThisResult = Nothing
End Function
I think one way to do it create a table that stores user accounts pending for approval. When user registers, populate this table with the userID or userName or set some flags indicating users who account has not been activated and who mails have been sent. Check this table when user logs in, if exist or flag not set, display "Activate your account to user"
Write a function that connects to the DB and use the userId to get the approval status from Aspnet_Membership table. The column name is IsApproved which is true or false
Dim user As MembershipUser = Membership.GetUser(userName);
Dim isApproved As Boolean = myMethodCheckIfUserIsApproved(user.ProviderUserKey); //userID
You should be able to call the Membership GetPassword method, passing Nothing in as the passwordAnswer parameter, which should just cause the password to be returned.
A disclaimer on this approach, however: we have implemented our own membership provider and SQL, and I don't have the original code to validate this against, so there may be something in the default provider that would prevent this approach, but it is worth trying.
EDIT:
In the case that the password is hashed, a possible solution to the problem is to perform a direct database query against the users table to get the state of the IsApproved flag. You could do this either before or after the call to GetUser, depending on how much you trust your end users (if you don't trust them, I would call it after in order to prevent someone from trying multiple users to see which are active).
UPDATE & ANSWER TO MY QUESTION
Hello everyone who replied to my question and thank you for your help,
It seems I was barking up the wrong tree by trying to validate the PASSWORD before trying to see if the account membership had been approved.
I have resolved the issue in a VERY SIMPLE WAY indeed.
This is how I did and I did not need to DIRECTLY interogate the database password field nor did i have to worry about hashing the password.
First of all I modified the default VALIDATELUSER call declaration....
in the SERVICES region of the ACCOUNTS MODEL
from...
Function ValidateUser(ByVal Username As String, ByVal Password As String) As Boolean
To...
Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef IsApproved As Boolean) As Boolean
This enabled me to call my newly modfied validation process also in the SERVICES region of the Accounts model where the ORGINIAL CODE was as follows...
Public Function ValidateUser(ByVal userName As String, ByVal password As String) As Boolean Implements IMembershipService.ValidateUser
If String.IsNullOrEmpty(userName) Then Throw New ArgumentException("Value cannot be null or empty.", "userName")
If String.IsNullOrEmpty(password) Then Throw New ArgumentException("Value cannot be null or empty.", "password")
Return _provider.ValidateUser(userName, password)
End Function
And the MODIFIED function which is now as follows...
Public Function ValidateUser(ByVal Username As String, ByVal Password As String, ByRef Approved As Boolean) As Boolean Implements IMembershipService.ValidateUser
Dim ThisMember As MembershipUser = Nothing
Dim ThisResult As Boolean = Nothing
'
Approved = False
ThisResult = False
If String.IsNullOrEmpty(Username) Then
Throw New ArgumentException("Value cannot be null or empty.", "Username")
ElseIf String.IsNullOrEmpty(Password) Then
Throw New ArgumentException("Value cannot be null or empty.", "Password")
ElseIf _Provider.ValidateUser(Username, Password) Then
ThisResult = True
Else
ThisMember = _Provider.GetUser(Username, False)
If (ThisMember Is Nothing) = False Then
Approved = ThisMember.IsApproved
End If
End If
Return ThisResult
ThisMember = Nothing
ThisResult = Nothing
End Function
I'm much happier with this prcoedure than with messing about with direct manipulation of the DB and also hashing the password.
So in effect, it was more about the original sequence of processing being back to front....
IE.
Not (1)validate login credentials then (2)check if email confirmed? (via link in welcome message)
but rather...
(1)Email Confirmed then (2)validate login credentials

Converting SMTP Mailer to CDOSYS in classic ASP for contact form

I am currently in the process of updating many test sites on an old server so that they won't break when the old server gets discontinued in the next couple months. The contact form for one site in particular is already broken. When a user clicks on submit after filling in their information, they are presented with this error:
Server object error 'ASP 0177 : 800401f3'
Server.CreateObject Failed
/contactsubmit.asp, line 79
800401f3
Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
Mailer.FromName = "Web Visitor"
If request("email") <> "" then
Mailer.replyto = request("email")
Else
Mailer.replyto = "noEmailEntered#domain.com"
End If
Mailer.FromAddress = "my#email.com"
Mailer.RemoteHost = "hostserver"
If TempTest = TRUE then
Else
Mailer.AddRecipient siteOwner, ContactEmail
If ContactCC <> "" then
Mailer.AddCC siteOwner, ContactCC
End If
End If
If DesignerEmail <> "" then
Mailer.AddBCC DesignerEmail, DesignerEmail
End If
Mailer.Subject = siteOwner & " Contact Form"
Mailer.ContentType = "text/html"
Mailer.BodyText = strBody
If Mailer.SendMail then
response.redirect "contact.asp?sent=yes"
Else
response.redirect "contact.asp?sent=no"
End If
I was told that SMTP isn't the way that emails need to get sent anymore so I tried changing it all to CDOSYS. But the funny thing is, there are a lot more sites on this server that I have tested using the same SMTP code that work.
Changes using CDOSYS:
Set Mailer = Server.CreateObject("CDO.Message")
Mailer.From = "Web Visitor <my#email.com>"
If request("email") <> "" then
Mailer.ReplyTo = request("email")
Else
Mailer.ReplyTo = "noEmailEntered#domain.com"
End If
Mailer.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "hostserver"
If TempTest = TRUE then
Else
Mailer.AddRecipient siteOwner, ContactEmail
If ContactCC <> "" then
Mailer.Cc siteOwner, ContactCC
End If
End If
If DesignerEmail <> "" then
Mailer.Bcc DesignerEmail, DesignerEmail
End If
Mailer.Subject = siteOwner & " Contact Form"
Mailer.HTMLBody = strBody
If Mailer.Send then
response.redirect "contact.asp?sent=yes"
Else
response.redirect "contact.asp?sent=no"
End If
But now I get this error:
Microsoft VBScript runtime error '800a01b6'
Object doesn't support this property or method: 'Mailer.AddRecipient'
/contactsubmit.asp, line 89
I have tried changing it to Mailer.Add and to Mailer.AddAddress with no luck. Does anyone know how I can get around this error and hopefully get this to work? I've never worked with mail servers before so I apologize if this is an easy fix, but I've searched for the past 3 hours and can't come up with a good alternative to .AddRecipient.
The CDO.Message object simply has the string properties of To, Cc and Bcc to which you assign a standard semi-colon delimited list of smtp email addresses for example:
"Joe Bloggs" <joeB#somecompany.com>; "Fred Smith" <fSmith#smiths.co.uk>
Try to execute the below simplest way of sending mail using CDO and then take the relevant fields from it and apply to your script:
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.From="mymail#mydomain.com"
myMail.To="someone#somedomain.com"
myMail.TextBody="This is a message."
myMail.Send
set myMail=nothing
As you can see the way to add recipient is like this:
myMail.To="someone#somedomain.com"
You can see more examples here
Hope this helps.

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