SmtpClient Email Not Sent, Not Caught and Not Logged? - asp.net

Our website was meant to send out a particular email, it didnt send the email and it also did not log the error which is unusual as i have a try catch setup which should log the entry in the try or catch section.
1) Why did it not log?
Should i not use Exception and instead use SmtpException and SmptFailedException. If i have this would it have made a difference? If so can you please provide an example.
2) The port we are currently using is 587. As our website is SSL i read we should be using 443 port instead. Would this have made a difference?
The below code is called asynchronously by using
ThreadPool.QueueUserWorkItem(new WaitCallback(SendInstructions), guid);
Which then calls a function that then calls the SendEmail Function below
public static bool SendEmail(String strToAddress, String strFromAddress, String strFromName, String strSubject, String strRecipientName, String strBody, String strEmbeddedImagePath, String strEmbeddedImageName, String strCCReminderEmail)
{
try
{
SmtpClient client = new SmtpClient();
client.EnableSsl = true;
using (MailMessage message = new MailMessage(
new MailAddress(strFromAddress, strFromName),
new MailAddress(strToAddress, strRecipientName)))
{
message.IsBodyHtml = true;
message.Subject = strSubject;
message.Body = strBody;
if (!string.IsNullOrEmpty(strCCReminderEmail))
message.CC.Add(strCCReminderEmail);
client.Send(message);
LogEmail(strFromAddress, strToAddress, strSubject, "Sent", strBody);
return true;
}
}
catch (Exception ex)
{
//log email
LogEmail(strFromAddress, strToAddress, strSubject, "Error", strBody);
throw;
}
}

I had a problem similar when using
ThreadPool.QueueUserWorkItem( new WaitCallback( ...
and then
System.Net.Mail.SmtpClient sC = new System.Net.Mail.SmtpClient(SMTPHost, SMTPPort);
the thread died without throwing an exception.
In my case, the main application thread is exiting before the background threads in the threadpool have had a chance to finish.
The threadpool creates Background worker threads which die as soon as
the main application thread terminates.
so I made a function to sleep 5 seconds and it worked.

Related

149.xxx.xxx.xxx is my address exception (C#, ASP.NET CORE 2.0, SMTP-client, MailKit)

Good day, dear collegues!
I'm trying to send email using SMTP-server, created by my collegue. I'm using .net core 2.0 this Identity.
When I run my application at debug-mode using my own computer -- it works perfectly.
When I run the same app on hosting it throws this exception:
SmtpCommandException: 149.xxx.xxx.xxx is my address
MailKit.Net.Smtp.SmtpClient.OnSenderNotAccepted(MimeMessage message, MailboxAddress mailbox, SmtpResponse response)
the hosting and the smtp-server have the same IP-address and work at the same computer.
I'm sure, that exception of form "149.xxx.xxx.xxx is my address" means, that smtp-server thinks, I'm spamer, trying to use its IP to be "whitelisted" -- and this server blocks me.
I've found this:
HELO is faked interface address
Type: forgery
Some spammers put the server's interface address they connect to in their HELO, maybe asuming it is whitelisted or something.
drop condition = ${if eq{[$interface_address]}{$sender_helo_name}}
message = $interface_address is my address
But the same hosting has many other web-applications, they don't have a problem with connection to the local server.
public async Task SendEmailAsync(string email, string subject, string message)
{
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("No reply", "XX#XXXX.XXX"));
emailMessage.To.Add(new MailboxAddress("", email));
emailMessage.Subject = subject;
emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Html)
{
Text = message
};
using (var client = new SmtpClient())
{
await client.ConnectAsync("localhost", 25, SecureSocketOptions.None);
await client.AuthenticateAsync("XX#XXXX.XXX", "Password");
await client.SendAsync(emailMessage);
await client.DisconnectAsync(true);
}
}
I tried to use its address instead of "localhost". But it throws the same exception.
What should I do? How to say a smtp-server that I'm not spamer, that I'm just physically situated on its IP-address, on the same computer?
Yes, now I've done it!
I needed to use direct connection to local mail server (without SMTP, this is very important).
How to implement direct connection? My web-server uses Linux Ubuntu system. So I needed to use the Shell (Ubuntu terminal).
Firstly I've tested it manually: when I type "sendmail" (command for direct usage of local mail server) it requires email of recipient.
And I needed to type in terminal:
$ sendmail xxx#mail.com
subject:My subject //this is new line
to:xxx#mail.com // this is new line
from:kkk#mydomain.com // this is new line
Here I can write many lines of my letter's body.
. // this is the point in new line (the only symbol) to show this is end of the letter. Next keyboard "enter" means to send finally.
To use these commands, I needed to create new process (the same as to give command "sendmail").
So, instead of this all:
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("No reply", "XX#XXXX.XXX"));
emailMessage.To.Add(new MailboxAddress("", email));
emailMessage.Subject = subject;
emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Html)
{
Text = message
};
using (var client = new SmtpClient())
{
await client.ConnectAsync("localhost", 25, SecureSocketOptions.None);
await client.AuthenticateAsync("XX#XXXX.XXX", "Password");
await client.SendAsync(emailMessage);
await client.DisconnectAsync(true);
}
I've just inserted
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "sendmail";
info.Arguments = $"{email}";
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("from:kkk#mydomain.com");
sw.WriteLine($"to:{email}");
sw.WriteLine($"subject:{subject}");
sw.WriteLine(message);
sw.WriteLine(".");
}
}
p.WaitForExit();

How to call HTTP URL using wifi in J2ME code for BlackBerry 5.0 and above?

I am calling a web service from BlackBerry using J2ME code. When I try to open a connection using HttpConnection, it is checking only the GPRS connection. Now, I want to check the Wi-Fi connection and call a webservice through Wi-Fi.
The following code is my connection section. How to change the code for a Wi-Fi connection?
public boolean HttpUrl()
{
HttpConnection conn = null;
OutputStream out = null;
String url = "http://www.google.com";
try
{
conn = (HttpConnection) new ConnectionFactory().getConnection(url).getConnection();
if (conn != null)
{
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty("Content-Length", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
}
}
catch (Exception e)
{
return false;
}
finally
{
try
{
out.close();
}
catch (Exception e2)
{
}
}
//Only if exception occurs, we close the connection.
//Otherwise the caller should close the connection himself.
try
{
conn.close();
}
catch (Exception e1)
{
}
return true;
}
Check this way:
HttpConnection conn = null;
String URL = "http://www.myServer.com/myContent;deviceside=true;interface=wifi";
conn = (HttpConnection)Connector.open(URL);
source
Making Connections
Rafael's answer will certainly work if you know you'll only be using Wi-Fi.
However, if you only need to support BlackBerry OS 5.0 - 7.1, I would recommend that you do use the ConnectionFactory. Normally, you will not limit your code to only using one transport. You'll normally support (almost) any transport the device has, but you may want to code your app to choose certain transports first.
For example,
class ConnectionThread extends Thread
{
public void run()
{
ConnectionFactory connFact = new ConnectionFactory();
connFact.setPreferredTransportTypes(new int[] {
TransportInfo.TRANSPORT_TCP_WIFI,
TransportInfo.TRANSPORT_BIS_B,
TransportInfo.TRANSPORT_MDS,
TransportInfo.TRANSPORT_TCP_CELLULAR
});
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection("http://www.google.com");
if (connDesc != null)
{
HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
// TODO: set httpConn request method and properties here!
final int iResponseCode = httpConn.getResponseCode();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Dialog.alert("Response code: " +
Integer.toString(iResponseCode));
}
});
}
catch (IOException e)
{
System.err.println("Caught IOException: "
+ e.getMessage());
}
}
}
}
will choose the Wi-Fi transport if Wi-Fi is available, but use the GPRS connection if it isn't. I think this is generally considered best practice for the 5.0+ devices.
Request Properties
This code
conn.setRequestProperty("Content-Length", "application/x-www-form-urlencoded");
is not right. Content-Length should be the size, in bytes, of your HTTP POST parameters. See an example here.
Threading
Remember that making network connections is slow. Do not block the user interface by running this code on the main/UI thread. Put your code into a background thread to keep the UI responsive while you request remote content.

System.Net.Mail.SmtpFailedRecipientException: Mailbox name not allowed

I have written ASP.Net code to send mails from domain1.com mail account such as abc#domain1.com. This code work fine otherwise and the mails go. But when the same code executes on domain2.com, even with correct userid-pwd it gives the following error:
System.Net.Mail.SmtpFailedRecipientException: Mailbox name not allowed. The server response was: sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1) at System.Net.Mail.SmtpClient.Send(MailMessage message)
Is there any way to fix this?
If we have to add this domain in the list of allowed rcphosts, how can that be done?
The code written is something like this:
MailMessage message;
bool success;
message = new MailMessage(from, to);
Attachment file;
SmtpClient lclient;
lclient = new SmtpClient("mail.domain1.com", 587);
lclient.EnableSsl = false;
message.Body = body;
message.BodyEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
message.Subject = subject;
message.SubjectEncoding = System.Text.Encoding.UTF8;
lclient.SendCompleted += new
SendCompletedEventHandler(SendCompletedCallback);
lclient.UseDefaultCredentials = false;
lclient.Credentials = new NetworkCredential(userID, password);
try
{
lclient.Send(message);
success = true;
if (message != null)
message.Dispose();
success = true;
return (success);
}
catch (Exception ex)
{
//...
}
Thanks
The code works fine. The error is a rejection from the SMTP server. It would seem that the server, when accessed from Domain1, allows you to forward mail through it. When accessed from Domain2, it does not. Changing this would be a configuration on the SMTP server.
Note that this is common practice for SMTP services. They generally don't allow anybody to send mail through them to any address. (That would leave them wide open for spammers and other such unwanted activities.) So, if you're trying to access Domain1's SMTP service from outside of Domain1, it's probably just rejecting that.

Understanding how SmtpClient handles retries

I'm working against a GoogleApps account for sending event notifications from my (mvc) web-app. Usually everything works fine. When the system is asked to send more than 75 messages or so I'm seeing replies from the SMTP server:
Service not available, closing
transmission channel. The server
response was: 4.7.0 Try again later,
closing connection. (MAIL)
uf10sm1153163icb.17
However, the system is auto-retrying and anything my system is asked to send eventually (by everything i can tell as this point) making it out. But given how the code generates and sends the emails I don't understand how these re-tries are handled.
I'd like to try to slow down the transmission in hopes that whatever's causing the 'Service Not Available' condition will be placated if the submissions occur asynchronously. But from the looks of the code, it already is since i'm using a Try | catch block.
Here's the relevant bit of my facade code:
foreach (string email in recipientEmails)
{
try
{
EmailGateway.Instance.SendEmail(email, notificationSubject, notificationMessage);
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.LogMessage("ERROR! Unsent email is to: " + email );
}
Logger.Instance.LogMessage("Sent " + notificationSubject + " to " + email);
}
And here's the Gateway code (using System.Net.Mail;):
public virtual void SendEmail(string replyToAddress, string toEmailAddress, string subject, string body)
{
string destinationEmailAddress = toEmailAddress;
string fromEmailAddress = "my#address.com";
bool useSSL = "true";
MailMessage message = new MailMessage(fromEmailAddress, destinationEmailAddress, subject, body);
message.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.EnableSsl = useSSL;
smtp.Send(message);
}
So i'm catching both successes and fails into my logger table. What I don't understand is how I can see a log message for both a fail and then a success condition for the same email address. That indicates a 'retry' and, while i'm not surprised that the SmtpClient (the native .net assembly) can retry without explicit code asking it to, I don't see how my facade's code is being made to log both conditions.
SmtpClient is not retrying to send the email.
In your facade code as it is, you are always logging a success, whether you are getting an exception or not.
You should log success in the try block, otherwise you are catching the exception (logging failure), coming out of the catch block and logging success anyway, which is what you are observing.
foreach (string email in recipientEmails)
{
try
{
EmailGateway.Instance.SendEmail(email, notificationSubject, notificationMessage);
Logger.Instance.LogMessage("Sent " + notificationSubject + " to " + email);
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.LogMessage("ERROR! Unsent email is to: " + email );
}
}

Actionscript 2.0 Email form LoadVars with ashx .net handler

I have a flash as 2.0 file that i need to send emails via an asp handler. First off, is this possible? Second, if it is, how do i get the return to have a status=true?
the .net codebehind
public void ProcessRequest(HttpContext context)
{
//E-Mail Method
string response = "sent=success";
MailAddress fromAddress = new MailAddress(context.Request.QueryString["Email"].ToString(), context.Request.QueryString["Name"].ToString());
MailAddress toAddress = new MailAddress("emailInbox#site.com", "Goons");
MailMessage message = new MailMessage(fromAddress, toAddress);
message.Subject = context.Request.QueryString["Name"].ToString() + " sent you a message from the website.";
message.Body = context.Request.QueryString["Msg"].ToString();
SmtpClient client = new SmtpClient("mail.grassrootsdm.com");
// Include credentials if the server requires them.
NetworkCredential SMTPUserInfo = new NetworkCredential("mailsenderemail","password");
client.Credentials = SMTPUserInfo;
try {
client.Send(message);
}
catch (Exception ex) {
response = ex.ToString();
}
context.Response.Write(response);
}
the actionscript
if (i == 0) {
sendVars.Name = fieldName.field.text;
sendVars.Email = fieldEmail.field.text;
sendVars.Msg = fieldMsg.field.text;
sendVars.sendAndLoad("http://www.grassrootsdm.com/WebService/EmailHandler.ashx", statusVars, "POST");
statusMsg.text = "Sending...";
statusVars.onLoad = function(success:Boolean) {
if (success) {
if (statusVars.sent == "success") {
clearForm();
statusMsg.text = "Message sent";
}
} else {
statusMsg.text = "Error!";
}
clearInterval(clearStatus);
clearStatus = setInterval(clearStatusInt, 3000);
};
}
Yes, it is possible.
Read the important notes at the bottom of each codes pertain to sending and retrieving data from flash to .net page. Explanation of the code is in the comment inside the code.
Flash Part (Action Script 2)
//function to send invoke .net page to send email
//use other control/button to call this function
//important: in order for the 'onLoad' event to work correctly, this function has to be 'Void'
function sendMail():Void
{
//show status
statusMsg.text = "Sending...";
//create LoadVars object
var lv_in:LoadVars = new LoadVars();
var lv_out:LoadVars = new LoadVars();
//set onLoad event
lv_in.onLoad = function(success:Boolean)
{
//if success, meaning data has received from .net page, run this code
if (success)
{
//lv_in.sent is used to parsed out message/data from .Net page
statusMsg.text = "Message sent!" + lv_in.sent;
}
//if fail, run this code
else
{
statusMsg.text = "Error!";
}
}
//begin invoke .net page to send email
lv_out.sendAndLoad("SendMail.aspx", lv_in, "POST");
}
Important note:
The function that contain onLoad event, in this case sendMail function, has to be Void function, meaning it's not returning value. If this function return value, what happen is the function will be executed all the way without waiting for the data for the return data from .net page, thus the onLoad event will not be set properly.
.Net Part
I copied the OP's .Net code so assuming this code works when sending email.
public void ProcessRequest(HttpContext context)
{
//E-Mail Method
string response = "sent=Success&";
MailAddress fromAddress = new MailAddress(context.Request.QueryString["Email"].ToString(), context.Request.QueryString["Name"].ToString());
MailAddress toAddress = new MailAddress("emailInbox#site.com", "Goons");
MailMessage message = new MailMessage(fromAddress, toAddress);
message.Subject = context.Request.QueryString["Name"].ToString() + " sent you a message from the website.";
message.Body = context.Request.QueryString["Msg"].ToString();
SmtpClient client = new SmtpClient("mail.grassrootsdm.com");
// Include credentials if the server requires them.
NetworkCredential SMTPUserInfo = new NetworkCredential("mailsenderemail","password");
client.Credentials = SMTPUserInfo;
try
{
client.Send(message);
}
catch (Exception ex)
{
response = ex.ToString();
}
context.Response.Write(response);
}
Important note:
The only thing I changed from the OP's .Net code is the response message. It was originally "sent=success" which I changed to "sent=success&".
The reason for this is, if you want action script to parse the posted message/data from .Net, it will stop at & symbol, thus leave the rest of the message alone and only get the message under sent variable.

Resources