Email cron job (asp.net) with Quartz.Net not working - asp.net

I am trying to send peroidic emails with Quartz.net but with no success. Firstly, the email code portion below is verified to work as I opened a new project to test it out. When I opened the application.log, I can see the Log.DebugFormat messages and not exceptions was catched, however no email was being sent out. Any advice? Thanks.
public void Execute(IJobExecutionContext context)
{
try
{
Log.DebugFormat("{0}****{0}Job {1} fired # {2} next scheduled for {3}{0}***{0} Fired by {4}",
Environment.NewLine,
context.JobDetail.Key,
context.FireTimeUtc.Value.ToString("r"),
context.NextFireTimeUtc.Value.ToString("r"),
"James");
Log.DebugFormat("{0}***{0}Hello World!!!{0}***{0}", Environment.NewLine);
// Try send email
var mail = new Email();
mail.IsBodyHtml = true;
mail.MailAddresses = "ong1980#hotmail.com";
mail.MailSubject = "Test Cron Job";
var mailMessage = mail.CreateMailMessage();
var Th = new Thread(() => Email.Send(mailMessage, 6, 3000, true));
Th.Start();
}
catch (Exception ex)
{
Log.DebugFormat("{0}***{0}Failed: {1}{0}***{0}", Environment.NewLine, ex.Message);
}
}
App.Config:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="quartz" type="System.Configuration.NameValueSectionHandler,
System, Version=1.0.5000.0,Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
</configSections>
<quartz>
<add key="quartz.scheduler.instanceName" value="ServerScheduler"/>
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
<add key="quartz.threadPool.threadCount" value="10"/>
<add key="quartz.threadPool.threadPriority" value="2"/>
<add key="quartz.jobStore.misfireThreshold" value="60000"/>
<add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz"/>
</quartz>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.net>
<mailSettings>
<smtp deliveryMethod="Network" from="xxx#hotmail.com">
<network host="smtp.live.com" port="25" userName="xxx#hotmail.com" password="xxxxxxxxx" />
</smtp>
</mailSettings>
</system.net>
</configuration>

Ok happen that inside the /Quartz.Net/Quartz.Server.exe.config which should reside in the program files(x86), I miss out the connectionstring and mailsettings. Hope it can be a help for someone else.

Related

how to update a section in Web.Config using transforms?

In my Web.Config I have the following
<configuration>
<configSections>
/*some code*/
</configSections>
<appSettings>
<add key="KeyName" value="KeyValue"/>
</appSettings>
</configuration>
And I have used below code when deploying a web application project.
{
"QA": {
"ConfigChanges": [
{
"KeyName": "/configuration/appSettings/add[#key='KeyName']",
"Attribute": "value",
"Value": "NewKeyValue"
}
]
}
}
Above code finds the configuration with appkey name and overwrites it.
But how do we configure if it doesn't have any key, like smtp settings?
<system.net>
<mailSettings>
<smtp from="" deliveryMethod="Network">
<network host="smtp.gmail.com" port="57" defaultCredentials="true" />
</smtp>
</mailSettings>
</system.net>
I tried like below like using key, but I got the error.
{
"KeyName":"/configuration/system.net/mailSettings/smtp/network[#defaultCredentials='true']",
"Attribute": "host",
"Value": "test.com"
}
Failure while updating port of /configuration/system.net/mailSettings/smtp/network[#defaultCredentials='true']: 25
Can you please help me on this.

Received multiple email errors form Elmah

2 for my ASP.NET web pages .NET 4.0 app. I was using Enterpriselibrary to log and send error via email before the app was upgraded to .NET 4.0 but since its upgraded the EnterpriseLibrary logging has stopped logging so I have decided to switch to Elmah.
In part of my web.config file of the app:
<add name="ErrorHandler" type="myWebApp.ErrorHandlingModule, myWebApp" preCondition="managedHandler" />
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
As you can see there is already an Errorhandling module there (ErrorHandlingModule), which creates a custom error message ("ex" object in the following code). Originally in the ErrorHandlingModule:
try
{
ExceptionPolicy.HandleException(ex, "myWebApp Error Handling");
}
catch (Exception exApplicationBlockError)
{
try
{
EventLog log = new EventLog("Application");
log.Source = "Application Error";
log.WriteEntry(exApplicationBlockError.ToString(), EventLogEntryType.Error);
}
catch
{
}
}
Since I switch to Elmah:
try
{
//ExceptionPolicy.HandleException(ex, "myWebApp Error Handling");
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
catch (Exception exApplicationBlockError)
{
try
{
EventLog log = new EventLog("Application");
log.Source = "Application Error";
log.WriteEntry(exApplicationBlockError.ToString(), EventLogEntryType.Error);
}
catch
{
}
}
It works very well but the problem now is if there is any error it raises 2 error emails: one is the custom one, and the other the default Elmah one; and of course I only want the custom one.
I haven't added any extra Elmah ErrorFilter in the program but I do need to have the custom exception in my email.
Should I add a custom Elmah filter to filter out ALL the exceptions so Elmah won't send me the default error email? (Or any other suggestions?)
Also attach the elmah config in web.config file if it is any help:
<elmah>
<security allowRemoteAccess="false" />
<errorMail from="xxxx#myorg.au" to="xxxxx#myorg.au" subject="myWebApp error" async="true" />
</elmah>
Thanks in advance. Happy holiday!
If you don't want Elmah to email, then don't configure it to do so in the first place. Remove the module configuration:
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah">
And any other ErrorMail Elmah email related configuration such as
<errorMail from="xxxx#myorg.au" to="xxxxx#myorg.au" subject="myWebApp error" async="true" />
Silly me I should not need to include:
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
It's why the email was sent twice. But thanks for the help.

SmtpClient won't authenticate when inflated from web.config

When using the system.net/mail web.config settings to configure my SmtpClient, it fails to deliver emails, with an "protocol error" described best by Base64 encoding and authentication problems:
Example:
With the following Config
<system.net>
<mailSettings>
<smtp from="email#server.com">
<network host="servermail.outsourced.com"
port="2525"
defaultCredentials="false"
userName="username"
password="password"/>
</smtp>
</mailSettings>
</system.net>
And the Code:
var tmp = new SmtpClient();
MailMessage msg = new MailMessage();
msg.Subject = "test";
msg.From = new MailAddress("me#server.com");
msg.To.Add(new MailAddress("me#server.com"));
msg.Body = "test";
tmp.Send(msg);
Produces the error message:
System.Net.Mail.SmtpException: The server committed a protocol violation The server response was: UGFzc3dvcmQ6
at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response)
at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException
& exception)
at System.Net.Mail.SmtpClient.Send(MailMessage message)
However, in the following code where I manually set all the properties, the code runs without exception and the email is delivered.
var tmp2 = new SmtpClient("servermail.outsourced.com", 2525);
tmp2.Credentials = new NetworkCredential("username", "password");
tmp2.UseDefaultCredentials = false;
MailMessage msg = new MailMessage();
msg.Subject = "test";
msg.From = new MailAddress("me#server.com");
msg.To.Add(new MailAddress("me#server.com"));
msg.Body = "test";
tmp2.Send(msg);
I tried your config settings from within LINQPad against my hMailServer mail server, and they worked great. So, my guess is that the mail server you are communicating with is handshaking with the client in an unexpected fashion. When I was testing, I captured the SMTP log from my server, and here's what it looked like (sanitized, of course):
SENT: 220 my.mailserv.er ESMTP
RECEIVED: EHLO CLIENTAPP
SENT: 250-my.mailserv.er[nl]250-SIZE 25600000[nl]250 AUTH LOGIN
RECEIVED: AUTH login bWFpbHRlc3RAbXkubWFpbHNlcnYuZXI=
SENT: 334 UGFzc3dvcmQ6
RECEIVED: ***
SENT: 235 authenticated.
RECEIVED: MAIL FROM:<mailtest#mailserv.er>
SENT: 250 OK
RECEIVED: RCPT TO:<happyuser#mailserv.er>
SENT: 250 OK
RECEIVED: DATA
SENT: 354 OK, send.
My server requires SMTP AUTH, and you can see that after my client sends the AUTH command, the server responds with status code 334, and the base-64 encoded representation of Password:. So, I'd recommend turning on the trace functionality for the SmtpClient so you can see what is occurring during both scenarios.
I was running LINQPad 4.31, and my linqpad.config file contained:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<mailSettings>
<smtp from="mailtest#mailserv.er">
<network host="my.mailserv.er" port="25" userName="mailtest#mailserv.er" password="supersecure"/>
</smtp>
</mailSettings>
</system.net>
</configuration>
The LINQPad query was as follows:
SmtpClient mailer = new SmtpClient();
Guid g = Guid.NewGuid();
g.Dump("Message GUID");
MailMessage msg = new MailMessage();
msg.Subject = "Test:" + g;
msg.To.Add(new MailAddress("happyuser#mailserv.er"));
msg.Body = "I HAS A BODY";
mailer.Send(msg);
Add this for logging
Please comment what AuthenticationModules are used (you'll find them stated in the network.log).
On my box SmtpLoginAuthenticationModule# is constant used but there are others possible.
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
Try setting the deliveryMethod attribute to force the configuration to use the network-config
<system.net>
<mailSettings>
<smtp deliveryMethod="network" from="email#server.com">
<network host="servermail.outsourced.com"
port="2525"
defaultCredentials="false"
userName="username"
password="password"/>
</smtp>
</mailSettings>
</system.net>
Guys this code is ok i try using devsmtp for local machine and it work fine
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
Using tmp = New SmtpClient()
Dim msg As New MailMessage() With {.Subject = "test", .From = New MailAddress("youremail#domain.com")}
msg.[To].Add(New MailAddress("youremail#domain.com"))
msg.Body = "test"
tmp.Send(msg)
End Using
End Sub
please download the devsmtp for local machine from
http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=smtp4dev&DownloadId=269147&FileTime=129575689693530000&Build=20393

MVC - Users must reauthenticate on IIS Recycle

I need an app pool recycle to be completely transparent to the users of my web app.
Currently, upon an IIS 7 App Pool recycle all users logged into my web app are kicked out and are required to log back in (Context.User.Identity.IsAuthenticated is set to false). I employ SQL State Server, I use forms authentication and both are configured to use cookies. I was under the impression that .NET and/or IIS handles authentication of cookies.
However, every time the app pool is recycled Context.User.Identity.IsAuthenticated is set to false (and I've no idea where this occurs) my users are kicked out and are required to log back in. I can see that the session id remains the same throughout logins, I can also view this session information in the database/state server.
I can't tell if this is a session or a cookie problem.
Please Help!
Logon method:
public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, true); // uses FormsAuthentication.SetAuthCookie(username, true);
Session["userName"] = userName;
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Custom Controller Attribute:
public class CookieAuthorizeAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext lvContext = HttpContext.Current;
if (!lvContext.User.Identity.IsAuthenticated)
{
lvContext.Response.Redirect("~/Account/Logon");
}
else
{
FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthentication.RenewTicketIfOld(identity.Ticket);
}
base.OnActionExecuting(filterContext);
}
}
WebConfig:
<authentication mode="Forms">
<forms cookieless="UseCookies" loginUrl="~/Account/LogOn" slidingExpiration="true" name=".ASPXAUTH" requireSSL="false" timeout="2880" />
</authentication>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ScriptModule" />
<remove name="UrlRoutingModule" />
<remove name="Session" />
<remove name="FormsAuthentication" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="NHibernateMvcSessionModule" type="EpnNHibernateBase.NHibernateMvcSessionModule, EpnNHibernateBase" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
</modules>
I was able to find a solution on my own. The problem was not with how authentication was handled programmatically or how I was authenticating users. The problem was with how I had configured the authentication in IIS/web.config.
I carefully followed the steps in the links listed below:
Configuring Forms Authentication (IIS 7) (Branching out on every related section)
Configuring Machine Keys in IIS 7 <-- This one in particular
After having followed those steps closely I was able to correctly generate a machine key.
This machine key is as follows (with a fabricated key):
<machineKey decryptionKey="ASDF3WS545AS5D4F8254A12DAFA5SDF7,IsolateApps" validation="3DES" validationKey="A65A6S5DF46ASD4F89WEF6SAD2F4A68EF4AW65F4D3A2F4AS6DF89A98D4F6A5SD4F6A5SDF46ASD8F4A6S5DF46AS5D4F6AS5DF49AS8DF46AS5D4F6AS5DF46SAD5F,IsolateApps" />
Additionally, httpModules and system.webServer:modules sections in the web.config required the addition of the following modules:
<remove name="Session" />
<remove name="FormsAuthentication" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
Summary: From what I gather, cookies were being created and encrypted, but because there was no machine key I was unable to unencrypt the cookie, thus causing the need to reauthenticate.
have you tried storing the sessions in a database so they are persistent even if the process is recycled?
see here for howto
Reading your post closely, it looks like the real issue is that users are not logged back in automatically. This is handled by cookies assuming you are using forms authentication.
Once a user is logged in, their session state will be restored if you are using SQL to persist it.
To debug cookies, you can use Fiddler or other cookie sniffers.
Posting your web.config would be helpful as well.

Able to send email through .exe, but not ASP.NET?

I'm trying to send an email to an external address as part of a web app. I can send an email fine when using a simple executable running on the server:
private void button1_Click(object sender, EventArgs e)
{
MailMessage message = new MailMessage(welcomeMessageFrom, toAddress, welcomeMessageSubject, welcomeMessageSubject);
SmtpClient emailClient = new SmtpClient("mail.sortuv.com");
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(username, password);
emailClient.UseDefaultCredentials = false;
emailClient.Credentials = SMTPUserInfo;
emailClient.Send(message);
}
However, trying the same code from an ASP.NET page gives the following exception:
Mailbox unavailable. The server response was: 5.7.1 Unable to relay for <user's email>
I'm new to IIS but do you have suggestions on how to debug?
UPDATE: I had to specify the domain for the user as well. Still not sure why a regular .exe was ok without it. Hope this helps someone.
Seems a credential issue. The normal exe runs under your account.
The ASP.NET application run under the NETWORK SERVICE in Windows Server and ASPNET under Windows XP.
You have to use other credentials in order to successfully send email from ASP.NET
Try adding
emailClient .DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
Is this for IIS7 as I had a simular issue I had to enable the smtp service on the server
And set up the mail for each domain on there
Thanks for all the help guys, I just figured it out. I had to specify the domain:
SmtpClient emailClient = new SmtpClient(servername);
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(name, pass);
SMTPUserInfo.Domain = domain; // i.e. "foo.com"
emailClient.UseDefaultCredentials = false;
emailClient.Credentials = SMTPUserInfo;
emailClient.Send(message);
Are you setting anything your web.config, relating to mail parameters? IIRC, the web.config will override your code settings.
Also, something else you can do, is to enable logging, to actually see what the SmtpClient is sending.
You need to add some values to your .config file. Here is an example:
<configuration>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net" >
<listeners>
<add name="MyTraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="MyTraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="MyTraceFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log" />
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
</switches>
</configuration>
Here is a link with more info:
http://systemnetmail.com/faq/4.10.aspx

Resources