|
//------------------------------------------------------------------------------
// <copyright file="TemplatedMailWebEventProvider .cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Management {
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.Util;
using System.Net.Mail;
using System.Globalization;
using System.Web.Configuration;
using System.Text;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Security.Permissions;
using System.Threading;
public sealed class TemplatedMailWebEventProvider : MailWebEventProvider, IInternalWebEventProvider {
int _nonBufferNotificationSequence = 0;
string _templateUrl;
bool _detailedTemplateErrors = false;
class TemplatedMailErrorFormatterGenerator : ErrorFormatterGenerator {
int _eventsRemaining;
bool _showDetails;
bool _errorFormatterCalled;
internal TemplatedMailErrorFormatterGenerator(int eventsRemaining, bool showDetails) {
_eventsRemaining = eventsRemaining;
_showDetails = showDetails;
}
internal bool ErrorFormatterCalled {
get { return _errorFormatterCalled; }
}
internal override ErrorFormatter GetErrorFormatter(Exception e) {
Exception inner = e.InnerException;
_errorFormatterCalled = true;
while (inner != null) {
if (inner is HttpCompileException) {
return new TemplatedMailCompileErrorFormatter((HttpCompileException)inner, _eventsRemaining, _showDetails);
}
else {
inner = inner.InnerException;
}
}
return new TemplatedMailRuntimeErrorFormatter(e, _eventsRemaining, _showDetails);
}
}
internal TemplatedMailWebEventProvider() { }
public override void Initialize(string name, NameValueCollection config)
{
Debug.Trace("TemplatedMailWebEventProvider", "Initializing: name=" + name);
ProviderUtil.GetAndRemoveStringAttribute(config, "template", name, ref _templateUrl);
if (_templateUrl == null) {
throw new ConfigurationErrorsException(SR.GetString(SR.Provider_missing_attribute, "template", name));
}
_templateUrl = _templateUrl.Trim();
if (_templateUrl.Length == 0) {
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_provider_attribute, "template", name, _templateUrl));
}
if (!UrlPath.IsRelativeUrl(_templateUrl)) {
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_mail_template_provider_attribute,
"template", name, _templateUrl));
}
_templateUrl = UrlPath.Combine(HttpRuntime.AppDomainAppVirtualPathString, _templateUrl);
// VSWhidbey 440081: Guard against templates outside the AppDomain path
if (!HttpRuntime.IsPathWithinAppRoot(_templateUrl)) {
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_mail_template_provider_attribute,
"template", name, _templateUrl));
}
ProviderUtil.GetAndRemoveBooleanAttribute(config, "detailedTemplateErrors", name, ref _detailedTemplateErrors);
base.Initialize(name, config);
}
void GenerateMessageBody(
MailMessage msg,
WebBaseEventCollection events,
DateTime lastNotificationUtc,
int discardedSinceLastNotification,
int eventsInBuffer,
int notificationSequence,
EventNotificationType notificationType,
int eventsInNotification,
int eventsRemaining,
int messagesInNotification,
int eventsLostDueToMessageLimit,
int messageSequence,
out bool fatalError) {
StringWriter writer = new StringWriter(CultureInfo.InstalledUICulture);
MailEventNotificationInfo info = new MailEventNotificationInfo(
msg,
events,
lastNotificationUtc,
discardedSinceLastNotification,
eventsInBuffer,
notificationSequence,
notificationType,
eventsInNotification,
eventsRemaining,
messagesInNotification,
eventsLostDueToMessageLimit,
messageSequence);
CallContext.SetData(CurrentEventsName, info);
try {
TemplatedMailErrorFormatterGenerator gen = new TemplatedMailErrorFormatterGenerator(events.Count + eventsRemaining, _detailedTemplateErrors);
HttpServerUtility.ExecuteLocalRequestAndCaptureResponse(_templateUrl, writer, gen);
fatalError = gen.ErrorFormatterCalled;
if (fatalError) {
msg.Subject = HttpUtility.HtmlEncode(SR.GetString(SR.WebEvent_event_email_subject_template_error,
notificationSequence.ToString(CultureInfo.InstalledUICulture),
messageSequence.ToString(CultureInfo.InstalledUICulture),
SubjectPrefix));
}
msg.Body = writer.ToString();
msg.IsBodyHtml = true;
}
finally {
CallContext.FreeNamedDataSlot(CurrentEventsName);
}
}
internal override void SendMessage(WebBaseEvent eventRaised) {
WebBaseEventCollection events = new WebBaseEventCollection(eventRaised);
bool templateError;
SendMessageInternal(events, // events
DateTime.MinValue, // lastNotificationUtc
0, // discardedSinceLastNotification
0, // eventsInBuffer
Interlocked.Increment(ref _nonBufferNotificationSequence), // notificationSequence
EventNotificationType.Unbuffered, // notificationType
1, // eventsInNotification
0, // eventsRemaining
1, // messagesInNotification
0, // eventsLostDueToMessageLimit
MessageSequenceBase, // messageSequence
out templateError); // templateError
}
internal override void SendMessage(WebBaseEventCollection events,
WebEventBufferFlushInfo flushInfo,
int eventsInNotification,
int eventsRemaining,
int messagesInNotification,
int eventsLostDueToMessageLimit,
int messageSequence,
int eventsSent,
out bool fatalError) {
SendMessageInternal(events,
flushInfo.LastNotificationUtc,
flushInfo.EventsDiscardedSinceLastNotification,
flushInfo.EventsInBuffer,
flushInfo.NotificationSequence,
flushInfo.NotificationType,
eventsInNotification,
eventsRemaining,
messagesInNotification,
eventsLostDueToMessageLimit,
messageSequence,
out fatalError);
}
void SendMessageInternal(WebBaseEventCollection events,
DateTime lastNotificationUtc,
int discardedSinceLastNotification,
int eventsInBuffer,
int notificationSequence,
EventNotificationType notificationType,
int eventsInNotification,
int eventsRemaining,
int messagesInNotification,
int eventsLostDueToMessageLimit,
int messageSequence,
out bool fatalError) {
using (MailMessage msg = GetMessage()) {
msg.Subject = GenerateSubject(notificationSequence, messageSequence, events, events.Count);
GenerateMessageBody(
msg,
events,
lastNotificationUtc,
discardedSinceLastNotification,
eventsInBuffer,
notificationSequence,
notificationType,
eventsInNotification,
eventsRemaining,
messagesInNotification,
eventsLostDueToMessageLimit,
messageSequence,
out fatalError);
SendMail(msg);
}
}
internal const string CurrentEventsName = "_TWCurEvt";
public static MailEventNotificationInfo CurrentNotification {
get {
return (MailEventNotificationInfo)CallContext.GetData(CurrentEventsName);
}
}
}
public sealed class MailEventNotificationInfo {
WebBaseEventCollection _events;
DateTime _lastNotificationUtc;
int _discardedSinceLastNotification;
int _eventsInBuffer;
int _notificationSequence;
EventNotificationType _notificationType;
int _eventsInNotification;
int _eventsRemaining;
int _messagesInNotification;
int _eventsLostDueToMessageLimit;
int _messageSequence;
MailMessage _msg;
internal MailEventNotificationInfo(
MailMessage msg,
WebBaseEventCollection events,
DateTime lastNotificationUtc,
int discardedSinceLastNotification,
int eventsInBuffer,
int notificationSequence,
EventNotificationType notificationType,
int eventsInNotification,
int eventsRemaining,
int messagesInNotification,
int eventsLostDueToMessageLimit,
int messageSequence) {
_events = events;
_lastNotificationUtc = lastNotificationUtc;
_discardedSinceLastNotification = discardedSinceLastNotification;
_eventsInBuffer = eventsInBuffer;
_notificationSequence = notificationSequence;
_notificationType = notificationType;
_eventsInNotification = eventsInNotification;
_eventsRemaining = eventsRemaining ;
_messagesInNotification = messagesInNotification;
_eventsLostDueToMessageLimit = eventsLostDueToMessageLimit;
_messageSequence = messageSequence;
_msg = msg;
}
public WebBaseEventCollection Events {
get { return _events; }
}
public EventNotificationType NotificationType {
get { return _notificationType; }
}
public int EventsInNotification {
get { return _eventsInNotification; }
}
public int EventsRemaining {
get { return _eventsRemaining; }
}
public int MessagesInNotification {
get { return _messagesInNotification; }
}
public int EventsInBuffer {
get { return _eventsInBuffer; }
}
public int EventsDiscardedByBuffer {
get { return _discardedSinceLastNotification; }
}
public int EventsDiscardedDueToMessageLimit {
get { return _eventsLostDueToMessageLimit; }
}
public int NotificationSequence {
get { return _notificationSequence; }
}
public int MessageSequence {
get { return _messageSequence; }
}
public DateTime LastNotificationUtc {
get { return _lastNotificationUtc; }
}
public MailMessage Message {
get { return _msg; }
}
}
internal class TemplatedMailCompileErrorFormatter : DynamicCompileErrorFormatter {
int _eventsRemaining;
bool _showDetails;
internal TemplatedMailCompileErrorFormatter(HttpCompileException e, int eventsRemaining,
bool showDetails) :
base(e) {
_eventsRemaining = eventsRemaining;
_showDetails = showDetails;
_hideDetailedCompilerOutput = true;
_dontShowVersion = true;
}
protected override string ErrorTitle {
get {
return SR.GetString(SR.MailWebEventProvider_template_compile_error,
_eventsRemaining.ToString(CultureInfo.InstalledUICulture));
}
}
protected override string Description {
get {
if (_showDetails) {
return base.Description;
}
else {
return SR.GetString(SR.MailWebEventProvider_template_error_no_details);
}
}
}
protected override string MiscSectionTitle {
get {
if (_showDetails) {
return base.MiscSectionTitle;
}
else {
return null;
}
}
}
protected override string MiscSectionContent {
get {
if (_showDetails) {
return base.MiscSectionContent;
}
else {
return null;
}
}
}
}
internal class TemplatedMailRuntimeErrorFormatter : UnhandledErrorFormatter {
int _eventsRemaining;
bool _showDetails;
internal TemplatedMailRuntimeErrorFormatter(Exception e, int eventsRemaining,
bool showDetails) :
base(e) {
_eventsRemaining = eventsRemaining;
_showDetails = showDetails;
_dontShowVersion = true;
}
protected override string ErrorTitle {
get {
if (HttpException.GetHttpCodeForException(Exception) == 404) {
return SR.GetString(SR.MailWebEventProvider_template_file_not_found_error,
_eventsRemaining.ToString(CultureInfo.InstalledUICulture));
}
else {
return SR.GetString(SR.MailWebEventProvider_template_runtime_error,
_eventsRemaining.ToString(CultureInfo.InstalledUICulture));
}
}
}
protected override string ColoredSquareTitle {
get { return null;}
}
protected override string ColoredSquareContent {
get { return null; }
}
protected override string Description {
get {
if (_showDetails) {
return base.Description;
}
else {
return SR.GetString(SR.MailWebEventProvider_template_error_no_details);
}
}
}
protected override string MiscSectionTitle {
get {
if (_showDetails) {
return base.MiscSectionTitle;
}
else {
return null;
}
}
}
protected override string MiscSectionContent {
get {
if (_showDetails) {
return base.MiscSectionContent;
}
else {
return null;
}
}
}
protected override string ColoredSquare2Title {
get {
if (_showDetails) {
return base.ColoredSquare2Title;
}
else {
return null;
}
}
}
protected override string ColoredSquare2Content {
get {
if (_showDetails) {
return base.ColoredSquare2Content;
}
else {
return null;
}
}
}
}
}
|