SmtpAppenderのソースを元に、SendEmailのところを差し替えただけだけど。
using System;
using System.IO;
using System.Net.Mail;
using log4net.Layout;
using log4net.Core;
using log4net.Util;
namespace log4net.MyAppender
{
/// <summary>
/// log4net の SmtpAppender とほぼ同じ機能だが、Charset を指定することが可能な Appender
/// </summary>
public class CdoAppender : log4net.Appender.BufferingAppenderSkeleton
{
#region Public Instance Constructors
/// <summary>
/// Default constructor
/// </summary>
/// <remarks>
/// <para>
/// Default constructor
/// </para>
/// </remarks>
public CdoAppender()
{
}
#endregion // Public Instance Constructors
#region Public Instance Properties
/// <summary>
/// Gets or sets a semicolon-delimited list of recipient e-mail addresses.
/// </summary>
/// <value>
/// A semicolon-delimited list of e-mail addresses.
/// </value>
/// <remarks>
/// <para>
/// A semicolon-delimited list of recipient e-mail addresses.
/// </para>
/// </remarks>
public string To
{
get { return m_to; }
set { m_to = value; }
}
/// <summary>
/// Gets or sets the e-mail address of the sender.
/// </summary>
/// <value>
/// The e-mail address of the sender.
/// </value>
/// <remarks>
/// <para>
/// The e-mail address of the sender.
/// </para>
/// </remarks>
public string From
{
get { return m_from; }
set { m_from = value; }
}
/// <summary>
/// Gets or sets the subject line of the e-mail message.
/// </summary>
/// <value>
/// The subject line of the e-mail message.
/// </value>
/// <remarks>
/// <para>
/// The subject line of the e-mail message.
/// </para>
/// </remarks>
public string Subject
{
get { return m_subject; }
set { m_subject = value; }
}
/// <summary>
/// Gets or sets the name of the SMTP relay mail server to use to send
/// the e-mail messages.
/// </summary>
/// <value>
/// The name of the e-mail relay server. If SmtpServer is not set, the
/// name of the local SMTP server is used.
/// </value>
/// <remarks>
/// <para>
/// The name of the e-mail relay server. If SmtpServer is not set, the
/// name of the local SMTP server is used.
/// </para>
/// </remarks>
public string SmtpHost
{
get { return m_smtpHost; }
set { m_smtpHost = value; }
}
/// <summary>
/// Obsolete
/// </summary>
/// <remarks>
/// Use the BufferingAppenderSkeleton Fix methods instead
/// </remarks>
/// <remarks>
/// <para>
/// Obsolete property.
/// </para>
/// </remarks>
[Obsolete("Use the BufferingAppenderSkeleton Fix methods")]
public bool LocationInfo
{
get { return false; }
set { ; }
}
/// <summary>
/// The mode to use to authentication with the SMTP server
/// </summary>
/// <remarks>
/// <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
/// <para>
/// Valid Authentication mode values are: <see cref="SmtpAuthentication.None"/>,
/// <see cref="SmtpAuthentication.Basic"/>, and <see cref="SmtpAuthentication.Ntlm"/>.
/// The default value is <see cref="SmtpAuthentication.None"/>. When using
/// <see cref="SmtpAuthentication.Basic"/> you must specify the <see cref="Username"/>
/// and <see cref="Password"/> to use to authenticate.
/// When using <see cref="SmtpAuthentication.Ntlm"/> the Windows credentials for the current
/// thread, if impersonating, or the process will be used to authenticate.
/// </para>
/// </remarks>
public SmtpAuthentication Authentication
{
get { return m_authentication; }
set { m_authentication = value; }
}
/// <summary>
/// The username to use to authenticate with the SMTP server
/// </summary>
/// <remarks>
/// <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
/// <para>
/// A <see cref="Username"/> and <see cref="Password"/> must be specified when
/// <see cref="Authentication"/> is set to <see cref="SmtpAuthentication.Basic"/>,
/// otherwise the username will be ignored.
/// </para>
/// </remarks>
public string Username
{
get { return m_username; }
set { m_username = value; }
}
/// <summary>
/// The password to use to authenticate with the SMTP server
/// </summary>
/// <remarks>
/// <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
/// <para>
/// A <see cref="Username"/> and <see cref="Password"/> must be specified when
/// <see cref="Authentication"/> is set to <see cref="SmtpAuthentication.Basic"/>,
/// otherwise the password will be ignored.
/// </para>
/// </remarks>
public string Password
{
get { return m_password; }
set { m_password = value; }
}
/// <summary>
/// The port on which the SMTP server is listening
/// </summary>
/// <remarks>
/// <note type="caution">Server Port is only available on the MS .NET 1.1 runtime.</note>
/// <para>
/// The port on which the SMTP server is listening. The default
/// port is <c>25</c>. The Port can only be changed when running on
/// the MS .NET 1.1 runtime.
/// </para>
/// </remarks>
public int Port
{
get { return m_port; }
set { m_port = value; }
}
/// <summary>
/// Gets or sets the priority of the e-mail message
/// </summary>
/// <value>
/// One of the <see cref="MailPriority"/> values.
/// </value>
/// <remarks>
/// <para>
/// Sets the priority of the e-mails generated by this
/// appender. The default priority is <see cref="MailPriority.Normal"/>.
/// </para>
/// <para>
/// If you are using this appender to report errors then
/// you may want to set the priority to <see cref="MailPriority.High"/>.
/// </para>
/// </remarks>
public MailPriority Priority
{
get { return m_mailPriority; }
set { m_mailPriority = value; }
}
public string ContentTransferEncoding
{
get { return m_contenttransferencoding; }
set { m_contenttransferencoding = value; }
}
public string Charset
{
get { return m_charset; }
set { m_charset = value; }
}
#endregion // Public Instance Properties
#region Override implementation of BufferingAppenderSkeleton
/// <summary>
/// Sends the contents of the cyclic buffer as an e-mail message.
/// </summary>
/// <param name="events">The logging events to send.</param>
override protected void SendBuffer(LoggingEvent[] events)
{
// Note: this code already owns the monitor for this
// appender. This frees us from needing to synchronize again.
try
{
StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture);
string t = Layout.Header;
if (t != null)
{
writer.Write(t);
}
for (int i = 0; i < events.Length; i++)
{
// Render the event and append the text to the buffer
RenderLoggingEvent(writer, events[i]);
}
t = Layout.Footer;
if (t != null)
{
writer.Write(t);
}
SendEmail(writer.ToString());
}
catch (Exception e)
{
ErrorHandler.Error("Error occurred while sending e-mail notification.", e);
}
}
#endregion // Override implementation of BufferingAppenderSkeleton
#region Override implementation of AppenderSkeleton
/// <summary>
/// This appender requires a <see cref="Layout"/> to be set.
/// </summary>
/// <value><c>true</c></value>
/// <remarks>
/// <para>
/// This appender requires a <see cref="Layout"/> to be set.
/// </para>
/// </remarks>
override protected bool RequiresLayout
{
get { return true; }
}
#endregion // Override implementation of AppenderSkeleton
#region Protected Methods
/// <summary>
/// メールを送信する。SMTPサーバ名は "smtpserver" 固定
/// </summary>
virtual protected void SendEmail(string messageBody)
{
// スタックフレーム上のローカル変数を捨ててからGCを起動したいので
// 別サブルーチンとして定義した
int gcGeneration = SendEmailSub(messageBody);
try
{
// 実際にメール送信するのは、iMsg が消滅する直前。
// GCを行うとすぐにメール送信できる
GC.Collect(gcGeneration);
}
catch (System.Runtime.InteropServices.COMException)
{
throw;
}
return;
}
virtual protected int SendEmailSub(string messageBody)
{
int gcGeneration = 0;
CDO.MessageClass iMsg = new CDO.MessageClass();
CDO.ConfigurationClass iConf = new CDO.ConfigurationClass();
gcGeneration = GC.GetGeneration(iMsg);
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"].Value = 2; // cdoSendUsingPort
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserver"].Value = m_smtpHost;
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"].Value = m_port;
switch (m_authentication)
{
case SmtpAuthentication.None:
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"].Value = 0;
break;
case SmtpAuthentication.Basic:
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"].Value = 1;
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"].Value = m_username;
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"].Value = m_password;
break;
case SmtpAuthentication.Ntlm:
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"].Value = 2;
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"].Value = m_username;
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"].Value = m_password;
break;
}
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpusessl"].Value = false; // SSL(TLS) は使わない
iConf.Fields["http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"].Value = 30; // タイムアウト30秒
iConf.Fields.Update();
iMsg.Configuration = iConf;
iMsg.To = m_to;
// if (m_bcc != "") { iMsg.BCC = m_bcc; }
iMsg.From = m_from;
iMsg.Subject = m_subject;
iMsg.TextBody = messageBody;
iMsg.TextBodyPart.ContentTransferEncoding = "7bit";
iMsg.TextBodyPart.Charset = "ISO-2022-JP";
iMsg.Send();
return gcGeneration;
}
#endregion // Protected Methods
#region Private Instance Fields
private string m_to;
private string m_from;
private string m_subject;
private string m_smtpHost;
// authentication fields
private SmtpAuthentication m_authentication = SmtpAuthentication.None;
private string m_username;
private string m_password;
// server port, default port 25
private int m_port = 25;
private MailPriority m_mailPriority = MailPriority.Normal;
// default ContentTransferEncoding is 8bit
private string m_contenttransferencoding = "base64";
// default charset is UTF-8
private string m_charset = "utf-8";
#endregion // Private Instance Fields
#region SmtpAuthentication Enum
/// <summary>
/// Values for the <see cref="SmtpAppender.Authentication"/> property.
/// </summary>
/// <remarks>
/// <para>
/// SMTP authentication modes.
/// </para>
/// </remarks>
public enum SmtpAuthentication
{
/// <summary>
/// No authentication
/// </summary>
None,
/// <summary>
/// Basic authentication.
/// </summary>
/// <remarks>
/// Requires a username and password to be supplied
/// </remarks>
Basic,
/// <summary>
/// Integrated authentication
/// </summary>
/// <remarks>
/// Uses the Windows credentials from the current thread or process to authenticate.
/// </remarks>
Ntlm
}
#endregion // SmtpAuthentication Enum
}
}
configはこんな感じで書いている。
<log4net debug="false">
<appender name="InfoSmtpAppender" type="log4net.MyAppender.CdoAppender">
<to value="info@example.com" />
<from value="info@example.com" />
<smtpHost value="smtphost" />
<bufferSize value="512" />
<lossy value="false" />
<evaluator type="log4net.Core.LevelEvaluator,log4net">
<threshold value="INFO" />
</evaluator>
<subject value="log4netからのインフォメーション" />
<contenttransferencoding value="7bit" />
<charset value="ISO-2022-JP" />
<layout type="log4net.Layout.PatternLayout,log4net">
<conversionPattern value="%property{log4net:HostName} :: %level :: %message %newlineLogger: %logger%newlineThread: %thread%newlineDate: %date%newlineNDC: %property{NDC}%newline%newline" />
</layout>
<!-- INFOレベルの時だけここのメールを出す -->
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
<acceptOnMatch value="true" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- LevelMatchFilter はマッチしなかった場合、次のルールに行く。デフォルトは accept なので最後にDenyAll を書く必要がある -->
</appender>
<root>
<!-- ログの蓄積はすべてのレベルで行い、メール送信のタイミングだけAppenderで制御する -->
<level value="DEBUG"/>
<appender-ref ref="InfoSmtpAppender"/>
</root>
</log4net>