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.
Related
I just want to send a reminder mail from my ASP.Net application to Outlook that automatically saves to the targeted Outlook Emailid calandar.
I have implemented this, but this is working on my system's Outlook only. It doesn't work on other systems.
protected void btSent_Click(object sender, EventArgs e) { SendMail("xyz#xyz.com", "xyx"); } public void SendMail(string targetMail, string shownTargetName) { MailAddress fromAddress = new MailAddress("xyz#xyz.com", "MailSendingProgram"); MailAddress toAddress = new MailAddress(targetMail, shownTargetName); String fromPassword = "xyz"; String subject = "Test Recurrence"; String body = #" Here you can put in any text that will appear in the body multilined and even in "; SmtpClient smtp = new SmtpClient { Host = "smtp.xyz.com", Port = 25, EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential(fromAddress.Address, fromPassword) };
using (MailMessage message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
}
)
{
try
{
ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
smtp.Send(message);
lbError.Text = "E-Mail sent!";
Microsoft.Office.Interop.Outlook.Application olApp = new Microsoft.Office.Interop.Outlook.Application();
CreateNewRecurringAppointment(olApp);
Marshal.ReleaseComObject(olApp);
}
catch
{
lbError.Text = "Sending failed, check your internet connection!";
}
}
}
public void CreateNewRecurringAppointment(Microsoft.Office.Interop.Outlook._Application OutlookApp) { Microsoft.Office.Interop.Outlook.AppointmentItem appItem = null; Microsoft.Office.Interop.Outlook.RecurrencePattern pattern = null; try { appItem = OutlookApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem) as Microsoft.Office.Interop.Outlook.AppointmentItem; // create a recurrence pattern = appItem.GetRecurrencePattern(); pattern.RecurrenceType = Microsoft.Office.Interop.Outlook.OlRecurrenceType.olRecursWeekly; pattern.StartTime = DateTime.Parse("8:35:00 AM"); pattern.EndTime = DateTime.Parse("9:35:00 PM"); // we can specify the duration instead of using the EndTime property pattern.Duration = 60; pattern.PatternStartDate = DateTime.Parse("03/9/2015"); pattern.PatternEndDate = DateTime.Parse("03/9/2015"); appItem.Subject = "Meeting with the Boss"; appItem.Body = "Test Appointment body"; appItem.Location = "P1"; appItem.ReminderSet = true; appItem.ReminderMinutesBeforeStart = 15; appItem.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceHigh; appItem.BusyStatus = Microsoft.Office.Interop.Outlook.OlBusyStatus.olBusy; appItem.Save(); appItem.Send();
//appItem.Display(true);
}
catch (Exception ex)
{
lbRecur.Text = ex.Message;
}
finally
{
if (pattern != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(pattern);
}
if (appItem != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(appItem);
}
}
}
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. You can read more about that in the Considerations for server-side Automation of Office article.
Consider using EWS (Exchange Web Services) or standard classes from BCLs (Base Class Libraries). You may find the EWS Managed API, EWS, and web services in Exchange article helpful.
I have method as below to send email, when ever any error occurs in our application. [Yes. sending errors through mails is a separate discussion]
public void EmailErrorDetails()
{
string strBodyMessage = string.Empty;
strBodyMessage = GetEmailBodyMessage();
if (strBodyMessage != String.Empty)
{
MailMessage emailMessage = new MailMessage();
emailMessage.From = new MailAddress(Constants.MailFrom);
emailMessage.To.Add(Constants.MailTo);
emailMessage.Subject = Constants.EmailSubject;
emailMessage.IsBodyHtml = true;
emailMessage.Body = string.Format(strBodyMessage);
SmtpClient client = new SmtpClient();
client.UseDefaultCredentials = false;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
client.Host = Constants.EmailHostAddress;
client.Port = Convert.ToInt32(Constants.EmailPort);
client.Credentials = new NetworkCredential(Constants.MailFrom, Constants.MailFromPassword);
client.Send(emailMessage);
}
}
I want to make this method run asynchronously in background, and the execution to move ahead.
I read that [client.Send] itself uses asynchronous calling. So is there any benefit making the above method call asynchronous way, and if yes how can I achieve this?
I read that client.Send uses asynchronous calling
Assuming client is actually an SmtpClient, then Send does not use asynchronous calling. SmtpClient has a specific method for sending emails asynchronously and it's called SendAsync - if you want to send an email in the background, use this instead of Send.
I have a couple of methods already to send an email message syncronously.
If an email fails, I use this fairly standard code:
static void CheckExceptionAndResend(SmtpFailedRecipientsException ex, SmtpClient client, MailMessage message)
{
for (int i = 0; i < ex.InnerExceptions.Length -1; i++)
{
var status = ex.InnerExceptions[i].StatusCode;
if (status == SmtpStatusCode.MailboxBusy ||
status == SmtpStatusCode.MailboxUnavailable ||
status == SmtpStatusCode.TransactionFailed)
{
System.Threading.Thread.Sleep(3000);
client.Send(message);
}
}
}
However, I'm trying to achieve the same using SendAsync(). This is the code I have so far:
public static void SendAsync(this MailMessage message)
{
message.ThrowNull("message");
var client = new SmtpClient();
// Set the methods that is called once the event ends
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
// Unique identifier for this send operation
string userState = Guid.NewGuid().ToString();
client.SendAsync(message, userState);
// Clean up
message.Dispose();
}
static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this operation.
String token = (string)e.UserState;
if (e.Error.IsNotNull())
{
// Do somtheing
}
}
The question is using token and/or e.Error how do I get the exception so that I can make the necessary checks for StatusCode and then resend?
I've been Googling all afternoon but havn't found anything positive.
Any advice appreciated.
e.Error already has the Exception that occurred while sending the email async. You can check the Exception.Message, Exception.InnerException, Exception.StackTrace, etc. to get further details.
Update:
Check if the Exception is of type SmtpException and if it is, you can query the StatusCode. Something like
if(e.Exception is SmtpException)
{
SmtpStatusCode code = ((SmtpException)(e.Exception)).StatusCode;
//and go from here...
}
And check here for further details.
I have been experimenting with WP7 apps today and have hit a bit of a wall.
I like to have seperation between the UI and the main app code but Ive hit a wall.
I have succesfully implemented a webclient request and gotten a result, but because the call is async I dont know how to pass this backup to the UI level. I cannot seem to hack in a wait for response to complete or anything.
I must be doing something wrong.
(this is the xbox360Voice library that I have for download on my website: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ which I am porting to WP7 as a test)
here is the backend code snippet:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
and this is the front end code:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
Now I understand I need to place something in ClientDownloadStringCompleted but I am unsure what.
The problem you have is that as soon as an asynchronous operation is introduced in to the code path the entire code path needs to become asynchronous.
Because GetResponse calls DownloadStringAsync it must become asynchronous, it can't return a string, it can only do that on a callback
Because GetGamer calls GetResponse which is now asynchronous it can't return a XboxGamer, it can only do that on a callback
Because GetGamerDetails calls GetGamer which is now asynchronous it can't continue with its code following the call, it can only do that after it has received a call back from GetGamer.
Because GetGamerDetails is now asynchronous anything call it must also acknowledge this behaviour.
.... this continues all the way up to the top of the chain where a user event will have occured.
Here is some air code that knocks some asynchronicity in to the code.
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
As you can see async programming can get realy messy.
You generally have 2 options. Either you expose your backend code as an async API as well, or you need to wait for the call to complete in GetResponse.
Doing it the async way would mean starting the process one place, then return, and have the UI update when data is available. This is generally the preferred way, since calling a blocking method on the UI thread will make your app seem unresponsive as long as the method is running.
I think the "Silverlight Way" would be to use databinding. Your XboxGamer object should implement the INotifyPropertyChanged interface. When you call GetGamer() it returns immediately with an "empty" XboxGamer object (maybe with GamerTag=="Loading..." or something). In your ClientDownloadStringCompleted handler you should deserialize the returned XML and then fire the INotifyPropertyChanged.PropertyChanged event.
If you look at the "Windows Phone Databound Application" project template in the SDK, the ItemViewModel class is implemented this way.
Here is how you can expose asynchronous features to any type on WP7.
Here is the set-up:
I have a Notifications controller that is called from task scheduler 1x/day
The action method pulls upwards of 300 addresses, loops thru them and uses the SmtpClient class to send an individual e-mail to each recepient.
From what I can tell the process runs fine with no exceptions ... except that not all e-mails are being delivered. Anyone have any ideas on what is going on and how to resolve?
Here is the code:
foreach (var emp in division.Users)
{
var fromAddress = "myfromaddress";
var mailServer = "mymailserver";
var toEmail = emp.EmailAddress;
var message = new MailMessage(fromAddress, toEmail)
{
Subject = subject,
Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>",
IsBodyHtml = true
};
var client = new SmtpClient(mailServer);
client.Send(message);
}
UPDATE:
Adding a pause in between sending e-mails resolves the problem. But why does this work? And is there a better way (e.g. using Async()) that would equally resolve the issue in a better way???
Updated code ...
foreach (var emp in division.Users)
{
var fromAddress = "myfromaddress";
var mailServer = "mymailserver";
var toEmail = emp.EmailAddress;
var message = new MailMessage(fromAddress, toEmail)
{
Subject = subject,
Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>",
IsBodyHtml = true
};
var client = new SmtpClient(mailServer);
client.Send(message);
Thread.Sleep(3000); // Wait 3s until sending next message
}
there is a default timeout with the smtp client and default value is 100sec
more info here
If you are not having any exceptions I'd check SPAM folders and email addresses. I'd also try sending an email manually from your outlook to one of the addresses that didn't recieve a message.
On a side note, unless you are using different mail servers, I think you can change this code to
var client = new SmtpClient(mailServer);
var mailServer = "mymailserver";
foreach (var emp in division.Users)
{
var fromAddress = "myfromaddress";
var toEmail = emp.EmailAddress;
var message = new MailMessage(fromAddress, toEmail)
{
Subject = subject,
Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>",
IsBodyHtml = true
};
client.Send(message);
}
You might also try SendAsync method of the SmtpClient class, like this:
// setup the callback method when the send finishes
client.SendCompleted += SendComplete; //new SendCompletedEventHandler(smtpSender_SendCompleted);
// send the email
client.SendAsync(message, null);
private void SendComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
// do stuff on complete
}
I would strongly advice on using SmtpClient.SendAsync() as Send() is blocking.
I would check the logs of the SMTP server that you're sending to. Note: sending your own emails are more likely to end in Junk mail than using a trusted provider.
Edit: added sample SendAsync code
smtpClient.SendCompleted += smtpClient_SendCompleted;
static void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
Log.ErrorFormat("Async Mail exception {0} :: {1}",
e.Error.GetType().Name, e.Error.Message);
}
}