简体   繁体   English

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

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

I would like to attach a file with the log sent by the log4net smtp appender. 我想用log4net smtp附加程序发送的日志附加一个文件。 This would allow us to include screenshots or input file data with the email log. 这将使我们能够在电子邮件日志中包含屏幕截图或输入文件数据。

Is there anyway to do this automatically out of the box. 无论如何,开箱即用即可自动执行此操作。 I can't seem to find any information on this, and am guessing we would need to either do this separate to the log4net logging or write the information inside the log (but that would need us to deserialise it after receiving the email). 我似乎找不到任何相关信息,并且猜测我们将需要将其独立于log4net日志记录,或者将信息写入日志中(但这需要我们在收到电子邮件后反序列化)。

You can do it with your own smtp appender, here is the code I use to send mail to multiple users, with a custom subject and attachment: 您可以使用自己的smtp附加程序来完成此操作,这是我用来向具有多个自定义主题和附件的多个用户发送邮件的代码:

  • In the config file 在配置文件中

For the custom subject: 对于自定义主题:

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

For the multiple recipients: 对于多个收件人:

email1@domain.com;email2@domain.com;...
  • In your log class 在您的日志类中

The code you have to call everytimes you want to add an attachment. 您每次想添加附件时必须调用的代码。
Careful, you have to adapt this one to your program! 小心,您必须使这一程序适应您的程序!

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));
        }
    }
}

And the big one, the custom appender: 还有一个是自定义附加程序:

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)));
    }
}

This is not supported. 不支持。 It would also be quite hard to support because only a few logging targets can support attaching files. 这也将很难支持,因为只有少数日志记录目标可以支持附加文件。

But you could - as a kind of work around - generate HTML log messages and use data URIs to embed binary data and especially images. 但是,作为一种替代方法,您可以生成HTML日志消息并使用数据URI嵌入二进制数据,尤其是图像。

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

SeleniumLog is an app built just for that - attaching screenshots and any arbitrary files/binaries to the log. SeleniumLog是一个专门为此目的而构建的应用程序-将屏幕快照和任何任意文件/二进制文件附加到日志中。 It's quite heavy duty and can handle hundreds and thousands of screenshots effortlessly. 这是非常繁重的工作,可以轻松处理成千上万的屏幕截图。 You could create an appender for it, or just wait as I heard they're working on a log4net plugin for it, among other things. 您可以为此创建一个附加程序,或者等我听说他们正在为此使用log4net插件时,再进行其他操作。

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

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