不能在多封邮件中重复使用电子邮件附件

本文关键字:电子邮件 不能 | 更新日期: 2023-09-27 18:01:27

我目前在MVC3中提供一个表单,供用户填写一些字段并附加一个文件。在提交时,我将张贴的信息(附附件)发送了两次…一封寄给海报作为收据,另一封寄给另一个目标邮箱。

我遇到的问题是第一封电子邮件成功发送了正确的附件。第二封电子邮件发送时附带一个大小为0的附件文件。似乎在我从文件上传中创建附件对象后,我不能再次使用它。使用调试器,我可以看到文件上传对象仍然在内存中,但其ContentLength变为0。

那么在下面的例子中,如果我将代码简化如下:

public static void SendDummyEmail1()
{
    using (var mailMessage = new MailMessage("from@email.com", "to@email.com"))
    {
        mailMessage.Subject = "Email Subject"
        mailMessage.Body = Razor.Parse(template, (dynamic)dynamicTokens);
        mailMessage.IsBodyHtml = true;
        if (_fileUpload != null && _fileUpload.ContentLength > 0)
        {
            var attachment = new Attachment(_fileUpload.InputStream, _fileUpload.FileName, MediaTypeNames.Application.Octet);
            attachment.ContentDisposition.FileName = Path.GetFileName(_fileUpload.FileName);
            mailMessage.Attachments.Add(attachment);
        }
        SendMail(mailMessage);
    }
}
public static void SendMail(MailMessage message)
{
    var client = new SmtpClient
    {
        Host = ConfigurationManager.AppSettings[SmtpHostname],
        Port = Convert.ToInt32(ConfigurationManager.AppSettings[SmtpPortNumber]),
        UseDefaultCredentials = true,
        Credentials = CredentialCache.DefaultNetworkCredentials,
        DeliveryMethod = SmtpDeliveryMethod.Network,
        EnableSsl = true,  
    };
    // Work around remote certificate validation
    // Ref: http://stackoverflow.com/questions/777607/the-remote-certificate-is-invalid-according-to-the-validation-procedure-using
    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
    client.Send(message);
}

如果我连续两次调用上面的方法,第一封电子邮件将成功通过。第二封邮件将通过,但没有附件,因为ContentLength变为0。

SendDummyEmail1();
SendDummyEmail1();

不能在多封邮件中重复使用电子邮件附件

我认为在您的情况下_fileUpload.InputStream.CanSeek等于false,这意味着您不能再次将它(Position = 0)卷起来并从中读取。尝试先将上传的文件流复制到内存流中,然后使用它来代替初始流,如下所示:

MemoryStream ms = new MemoryStream();
_fileUpload.InputStream.CopyTo(ms);
byte[] data = ms.ToArray();
SendDummyEmail1(data);
SendDummyEmail1(data);
public static void SendDummyEmail1(byte[] fileContent)
{
 ...
 var attachment = new Attachment(new MemoryStream(fileContent), ...
}

使用内存流作为实例变量,而不是_fileUpload。然后为每封邮件克隆一个新的steam(所以不要有多个消费者)。记得在写入后重置流,以便从开头

读取附件

将上传的文件存储在服务器上,并使用附件中的文件路径

var attachment = new Attachment(filePath, MediaTypeNames.Application.Octet);

发送邮件后如有需要,请删除上传的文件