繁体   English   中英

将文件(例如屏幕截图)附加到log4net smtp附加程序

[英]Attach file (e.g. screenshot) to log4net smtp appender

我想用log4net smtp附加程序发送的日志附加一个文件。 这将使我们能够在电子邮件日志中包含屏幕截图或输入文件数据。

无论如何,开箱即用即可自动执行此操作。 我似乎找不到任何相关信息,并且猜测我们将需要将其独立于log4net日志记录,或者将信息写入日志中(但这需要我们在收到电子邮件后反序列化)。

您可以使用自己的smtp附加程序来完成此操作,这是我用来向具有多个自定义主题和附件的多个用户发送邮件的代码:

  • 在配置文件中

对于自定义主题:

<layoutSubject type="log4net.Layout.PatternLayout,log4net">
    <conversionPattern value="Custom subject %level in application" />
</layoutSubject>

对于多个收件人:

email1@domain.com;email2@domain.com;...
  • 在您的日志类中

您每次想添加附件时必须调用的代码。
小心,您必须使这一程序适应您的程序!

private static void AddAttachment(string Attachment)
{
    if (!string.IsNullOrEmpty(Attachment))
    {
        if (File.Exists(Attachment))
        {
            foreach (IAppender Appender in Log.log.Logger.Repository.GetAppenders())
            {
                if (Appender.GetType().ToString().IndexOf(".SmtpCustomAppender") != -1)
                {
                    ((SmtpCustomAppender)(Appender)).Attachment = Attachment;
                }
            }
        }
        else
        {
            VPLog.Log4Net.LogWarning(string.Format("Le fichier {0} est introuvable sur le disque, il sera ignoré.", Attachment));
        }
    }
}

还有一个是自定义附加程序:

public class SmtpCustomAppender : log4net.Appender.SmtpAppender
{
    public SmtpCustomAppender()
        : base()
    {
    }
    public ILayout LayoutSubject { get; set; }
    public bool IsBodyHtml { get; set; }
    public string Attachment { get; set; }

    protected override void SendEmail(string messageBody)
    {
        // .NET 2.0 has a new API for SMTP email System.Net.Mail
        // This API supports credentials and multiple hosts correctly.
        // The old API is deprecated.

        // Create and configure the smtp client
        SmtpClient smtpClient = new SmtpClient();
        if (!String.IsNullOrEmpty(this.SmtpHost))
        {
            smtpClient.Host = this.SmtpHost;
        }
        smtpClient.Port = this.Port;
        smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
        smtpClient.EnableSsl = this.EnableSsl;

        if (Authentication == SmtpAuthentication.Basic)
        {
            // Perform basic authentication
            smtpClient.Credentials = new System.Net.NetworkCredential(Username, Password);
        }
        else if (Authentication == SmtpAuthentication.Ntlm)
        {
            // Perform integrated authentication (NTLM)
            smtpClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
        }

        using (System.Net.Mail.MailMessage mailMessage = new System.Net.Mail.MailMessage())
        {
            mailMessage.IsBodyHtml = IsBodyHtml;
            mailMessage.Body = messageBody;
            //mailMessage.BodyEncoding = BodyEncoding;
            mailMessage.From = new MailAddress(From);
            foreach(string emailTo in To.Split(';'))
                mailMessage.To.Add(emailTo);
            if (!String.IsNullOrEmpty(Cc))
            {
                foreach (string emailCc in Cc.Split(';'))
                    mailMessage.CC.Add(emailCc);
            }
            if (!String.IsNullOrEmpty(Bcc))
            {
                foreach (string emailBcc in Bcc.Split(';'))
                    mailMessage.Bcc.Add(emailBcc);
            }
            if (!String.IsNullOrEmpty(this.ReplyTo))
            {
                // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete:
                // 'ReplyTo is obsoleted for this type.  Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202'
//#if !NET_4_0
                //mailMessage.ReplyTo = new MailAddress(this.ReplyTo);
//#else
                mailMessage.ReplyToList.Add(new MailAddress(this.ReplyTo));
//#endif
            }
            mailMessage.Subject = this.Subject;
            //mailMessage.SubjectEncoding = m_subjectEncoding;
            mailMessage.Priority = this.Priority;

            #region on ajoute la ou les pièce(s) jointe(s)
            if (!string.IsNullOrEmpty(Attachment))
            {
                var attachments = Attachment.Split(';');
                foreach (var attach in attachments)
                {
                    if (!string.IsNullOrEmpty(attach.Trim()))
                    {
                        var path = attach.Trim();
                        try
                        {
                            var context = HttpContext.Current;
                            if (context == null) //context non web
                            {
                                //on teste s'il s'agit d'un chemin absolu ou non
                                if (!Path.IsPathRooted(path))
                                {
                                    path = Directory.GetCurrentDirectory() + "\\" + path;
                                }

                                if (File.Exists(path))
                                {
                                    //si le fichier spécifié existe bien, on l'ajoute en pièce jointe au mail
                                    AttachFile(mailMessage, path);
                                }
                                else
                                {
                                    // Sinon, on écrit dans le corps du mail que le fichier n'a pas été trouvé
                                    mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                                    mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                                    mailMessage.Body += "Fichier non trouvé: " + attach;
                                }
                            }
                            else //context web
                            {
                                //on teste s'il s'agit d'un chemin absolu ou non
                                if (!Path.IsPathRooted(path))
                                {
                                    path = context.Server.MapPath(path);
                                }

                                if (File.Exists(path))
                                {
                                    //si le fichier spécifié existe bien, on l'ajoute en pièce jointe au mail
                                    AttachFile(mailMessage, path);
                                }
                                else
                                {
                                    // Sinon, on écrit dans le corps du mail que le fichier n'a pas été trouvé
                                    mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                                    mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                                    mailMessage.Body += "Fichier non trouvé: " + attach;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // En cas d'erreur, on précise dans le corps du mail que le fichier n'a pu être joint
                            mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                            mailMessage.Body += IsBodyHtml ? "<br/>" : Environment.NewLine;
                            mailMessage.Body += string.Format("<b>Erreur lors de l'ajout de la piece jointe: {0}</b>", attach);

                            // On logge l'erreur avec le logger interne de log4net
                            VPLog.Log4Net.Log.log.Error(string.Format("Erreur lors de la pièe jointe: {0} (path: {1})", attach, path), ex);
                        }
                        finally
                        {
                            this.Attachment = "";
                        }
                    }
                }
            }
            #endregion

            // TODO: Consider using SendAsync to send the message without blocking. This would be a change in
            // behaviour compared to .NET 1.x. We would need a SendCompletedCallback to log errors.
            smtpClient.Send(mailMessage);
        }
    }


    /// <summary>
    /// On permet la customisation de l'objet du mail
    /// </summary>
    /// <param name="loggingEvent"></param>
    protected override void Append(log4net.Core.LoggingEvent loggingEvent)
    {
        if (this.BufferSize <= 1 && this.LayoutSubject != null)
        {
            #region Custo pour le sujet
            var subjectWriter = new StringWriter(System.Globalization.CultureInfo.InvariantCulture);
            LayoutSubject.Format(subjectWriter, loggingEvent);
            this.Subject = subjectWriter.ToString();
        #endregion
    }
    base.Append(loggingEvent);
}

/// <summary>
/// Attache une pièce jointe au mail
/// </summary>
/// <param name="mailMessage">mailMessage</param>
/// <param name="path">Chemin du fichier</param>
private void AttachFile(System.Net.Mail.MailMessage mailMessage, string path)
{
    var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    mailMessage.Attachments.Add(new Attachment(stream, Path.GetFileName(Attachment)));
    }
}

不支持。 这也将很难支持,因为只有少数日志记录目标可以支持附加文件。

但是,作为一种替代方法,您可以生成HTML日志消息并使用数据URI嵌入二进制数据,尤其是图像。

创建具有自己的smpt行为的自己的附加程序, 文章如何执行附加程序

SeleniumLog是一个专门为此目的而构建的应用程序-将屏幕快照和任何任意文件/二进制文件附加到日志中。 这是非常繁重的工作,可以轻松处理成千上万的屏幕截图。 您可以为此创建一个附加程序,或者等我听说他们正在为此使用log4net插件时,再进行其他操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM