To really know what is going on when the program is run by the Task Scheduler you can put Trace statements at vital steps in your code such as:
Trace.WriteLine("Start creating mail object");
and
Trace.WriteLine(string.Format("Exception occured: {0}\r\n{1}", ex.Message, ex.StackTrace);
Don't forget to put a Trace.WriteLine inside your exception handler so you know if something goes wrong.
You take control over where these statements are written by configuring listeners inside your .config file.
The following example adds an EventLogTraceListener object named myListener to the Trace.Listeners collection. The initializeData parameter specifies the name of the event log source that is to be passed to the EventLogTraceListener(String) constructor.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="myListener"
type="System.Diagnostics.EventLogTraceListener"
initializeData="TraceListenerLog" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
You can open the EventViewer by going to Start > eventvwr
Hope this helps you to figure out what the problem is because at this point it's anyone's guess.