Modifying the content type of an attachment in a C

2020-03-02 03:04发布

问题:

When I try to add an MHTML file as an attachment to an email message in VBScript, the ContentMediaType is incorrectly set to "message/rfc822" (RFC 822). From what I understand, this is correct according to Microsoft, but is incorrect according to RFC 2557 which states that it should be "multipart/related". This is a problem, because most (if not all) mail clients interpret "message/rfc822" as an email message. Since the file extensions ".mht" and ".mhtml" do not match any valid file extension of an email message, the mail client appends one of ".msg", ".eml", etc. to the filename. When a user opens the attachment, it opens as an email message and doesn't display correctly since an MHTML file and an email message are saved differently.

Sub SendEmail(FromAddress, ToAddress, Subject, Body, Attachment)
  Call Err.Clear
  On Error Resume Next

  Schema = "http://schemas.microsoft.com/cdo/configuration/"
  Set Configuration = Sys.OleObject("CDO.Configuration")
  Configuration.Fields.Item(Schema + "sendusing") = 2
  Configuration.Fields.Item(Schema + "smtpserver") = SMTPServer
  Configuration.Fields.Item(Schema + "smtpserverport") = 25
  Configuration.Fields.Item(Schema + "smtpauthenticate") = 1
  ' Configuration.Fields.Item(schema + "sendusername") = ""
  ' Configuration.Fields.Item(schema + "sendpassword") = ""
  Call Configuration.Fields.Update

  Set Message = Sys.OleObject("CDO.Message")
  Set Message.Configuration = Configuration
  Message.From = FromAddress
  Message.To = ToAddress
  Message.Subject = Subject
  Message.HTMLBody = Body
  If Not IsEmpty(Attachment) Then
    'CDO.Message.AddAttachment doesn't set the correct content media type for an MHTML file.
    Call Message.AddAttachment(Attachment)
  End If

  Call Message.Send
End Sub

When I run this code, Message.Attachments.Item(1).ContentMediaType is set to "message/rfc822". I need it to be "multipart/related" if Attachment (a string) ends with ".mht" or ".mhtml" (case-insensitive). I can do this with the following code.

If Len(Attachment) >= 4 And InStr(Len(Attachment) - 3, Attachment, ".mht", vbTextCompare) Or Len(Attachment) >= 4 And InStr(Len(Attachment) - 5, Attachment, ".mhtml", vbTextCompare) Then
  Message.Attachments.Item(1).ContentMediaType = "multipart/related"
End If

For some unknown reason, this undefines the attachment from Message.Attachments.

I've looked at manually adding the attachment per these instructions, but when I call Message.Attachments.Item(1).Fields.Update, the object becomes undefined. I think setting the attachments's ContentMediaType, implicitly invokes it's Fields's Update method which is what I think is responsible for this unexpected behavior.

How can I get around this and send an MHTML file with the "multipart/related" content type while maintaining the proper file extension?

回答1:

So your problem is that at least some email clients save MHTML attachment incorrectly if content type for the attachment is set as content-type="message/rfc822".

First, it is worth noting that your analysis of a root cause of the issue is flawed. You appear to be confused by where multipart/related MIME type comes into play. As a matter of fact, RFC 2557 does NOT state that body part corresponding to MHTML attachment must have content-type="multipart/related". Instead, MIME multipart/related is internal structure of MHTML file itself. Quoting Wikipedia article:

The content of an MHTML file is encoded as if it were an HTML e-mail message, using the MIME type multipart/related.

I.e. if you open MHTML file with text editor, you should see the following:

Content-Type: multipart/related; ...

Microsoft states that MHTML files should be served with content-type="message/rfc822" in KB937912. This is exactly what CDO does by default when you attach such file via AddAttachment method. I believe such behavior does not contradict RFC 2557 in any way. As per the RFC:

There are a number of document formats... that specify documents consisting of a root resource and a number of distinct subsidiary resources referenced by URIs within that root resource. There is an obvious need to be able to send such multi-resource documents in e-mail [SMTP], [RFC822] messages.

The standard defined in this document specifies how to aggregate such multi-resource documents in MIME-formatted [MIME1 to MIME5] messages for precisely this purpose.

To recap, you definitely should not set content type of MHTML attachment to multipart/related.

While message/rfc822 seems to be the way to use with MHTML files, it obviously triggers the problem you described in the question. I tested with Outlook 2010 and OWA 2010, and was able to reproduce it.

Alternative content types that are used by various email clients for MHTML attachments are application/octet-stream and application/x-mimearchive. These two didn't exhibit the problem in my tests.