Bug 998191, part 9: Use structured addresses in mime_generate_headers, r=irving

This commit is contained in:
Joshua Cranmer 2015-01-07 15:58:32 -06:00
Родитель 860af004a3
Коммит 4ada1a93e5
4 изменённых файлов: 57 добавлений и 69 удалений

Просмотреть файл

@ -37,6 +37,11 @@ public:
NS_FORWARD_MSGIWRITABLESTRUCTUREDHEADERS(mStructuredHeaders->)
NS_DECL_NSIMSGCOMPFIELDS
// Allow the C++ utility methods for people who use a concrete class instead
// of the interfaces.
using msgIStructuredHeaders::GetAddressingHeader;
using msgIWritableStructuredHeaders::SetAddressingHeader;
typedef enum MsgHeaderID
{
MSG_FROM_HEADER_ID = 0,

Просмотреть файл

@ -29,8 +29,10 @@
#include "nsMemory.h"
#include "nsCRTGlue.h"
#include <ctype.h>
#include "mozilla/mailnews/Services.h"
#include "mozilla/Services.h"
#include "nsIMIMEInfo.h"
#include "nsIMsgHeaderParser.h"
NS_IMPL_ISUPPORTS(nsMsgCompUtils, nsIMsgCompUtils)
@ -251,19 +253,6 @@ nsMsgStripLine (char * string)
//
#define UA_PREF_PREFIX "general.useragent."
#define ENCODE_AND_PUSH(name, structured, body, charset, usemime) \
{ \
PUSH_STRING((name)); \
convbuf = nsMsgI18NEncodeMimePartIIStr((body), (structured), (charset), strlen(name), (usemime)); \
if (convbuf) { \
PUSH_STRING (convbuf); \
PR_FREEIF(convbuf); \
} \
else \
PUSH_STRING((body)); \
PUSH_NEWLINE (); \
}
char *
mime_generate_headers (nsMsgCompFields *fields,
const char *charset,
@ -278,7 +267,6 @@ mime_generate_headers (nsMsgCompFields *fields,
return nullptr;
}
bool usemime = nsMsgMIMEGetConformToStandard();
int32_t size = 0;
char *buffer = nullptr, *buffer_tail = nullptr;
bool isDraft =
@ -287,40 +275,21 @@ mime_generate_headers (nsMsgCompFields *fields,
deliver_mode == nsIMsgSend::nsMsgQueueForLater ||
deliver_mode == nsIMsgSend::nsMsgDeliverBackground;
const char* pFrom;
const char* pTo;
const char* pCc;
const char* pNewsGrp;
const char* pFollow;
const char* pReference;
char *convbuf;
bool hasDisclosedRecipient = false;
nsAutoCString headerBuf; // accumulate header strings to get length
headerBuf.Truncate();
NS_ASSERTION (fields, "null fields");
if (!fields) {
*status = NS_ERROR_NULL_POINTER;
return nullptr;
}
pFrom = fields->GetFrom();
if (pFrom)
headerBuf.Append(pFrom);
pTo = fields->GetTo();
if (pTo)
headerBuf.Append(pTo);
pCc = fields->GetCc();
if (pCc)
headerBuf.Append(pCc);
pNewsGrp = fields->GetNewsgroups(); if (pNewsGrp) size += 3 * PL_strlen (pNewsGrp);
pFollow= fields->GetFollowupTo(); if (pFollow) size += 3 * PL_strlen (pFollow);
pReference = fields->GetReferences(); if (pReference) size += 3 * PL_strlen (pReference);
/* Multiply by 3 here to make enough room for MimePartII conversion */
size += 3 * headerBuf.Length();
/* Add a bunch of slop for the static parts of the headers. */
/* size += 2048; */
size += 2560;
@ -333,6 +302,9 @@ mime_generate_headers (nsMsgCompFields *fields,
buffer_tail = buffer;
nsCOMArray<msgIAddressObject> from;
fields->GetAddressingHeader("From", from, true);
// Make a new block of headers to store the usable headers in, and copy all
// headers from the original compose field.
nsCOMPtr<msgIWritableStructuredHeaders> finalHeaders =
@ -340,12 +312,6 @@ mime_generate_headers (nsMsgCompFields *fields,
rv = finalHeaders->AddAllHeaders(fields);
MOZ_ASSERT(NS_SUCCEEDED(rv), "This shouldn't fail");
// Don't emit any of these headers, handled by legacy code for now...
finalHeaders->DeleteHeader("from");
finalHeaders->DeleteHeader("to");
finalHeaders->DeleteHeader("cc");
finalHeaders->DeleteHeader("bcc");
bool hasMessageId = false;
if (NS_SUCCEEDED(fields->HasHeader("Message-ID", &hasMessageId)) &&
hasMessageId)
@ -360,18 +326,16 @@ mime_generate_headers (nsMsgCompFields *fields,
(deliver_mode != nsIMsgSend::nsMsgSaveAsDraft &&
deliver_mode != nsIMsgSend::nsMsgSaveAsTemplate))
{
int32_t receipt_header_type = nsIMsgMdnGenerator::eDntType;
fields->GetReceiptHeaderType(&receipt_header_type);
int32_t receipt_header_type = nsIMsgMdnGenerator::eDntType;
fields->GetReceiptHeaderType(&receipt_header_type);
// nsIMsgMdnGenerator::eDntType = MDN Disposition-Notification-To: ;
// nsIMsgMdnGenerator::eRrtType = Return-Receipt-To: ;
// nsIMsgMdnGenerator::eDntRrtType = both MDN DNT and RRT headers .
if (receipt_header_type != nsIMsgMdnGenerator::eRrtType)
ENCODE_AND_PUSH(
"Disposition-Notification-To: ", true, pFrom, charset, usemime);
finalHeaders->SetAddressingHeader("Disposition-Notification-To", from);
if (receipt_header_type != nsIMsgMdnGenerator::eDntType)
ENCODE_AND_PUSH(
"Return-Receipt-To: ", true, pFrom, charset, usemime);
finalHeaders->SetAddressingHeader("Return-Receipt-To", from);
}
}
@ -396,11 +360,6 @@ mime_generate_headers (nsMsgCompFields *fields,
((gmtoffset >= 0 ? gmtoffset : -gmtoffset) % 60));
buffer_tail += PL_strlen (buffer_tail);
if (pFrom && *pFrom)
{
ENCODE_AND_PUSH("From: ", true, pFrom, charset, usemime);
}
// X-Mozilla-Draft-Info
if (isDraft)
{
@ -570,15 +529,11 @@ mime_generate_headers (nsMsgCompFields *fields,
PR_Free (duppedFollowup);
}
if (pTo && *pTo) {
ENCODE_AND_PUSH("To: ", true, pTo, charset, usemime);
hasDisclosedRecipient = true;
}
if (pCc && *pCc) {
ENCODE_AND_PUSH("CC: ", true, pCc, charset, usemime);
hasDisclosedRecipient = true;
}
nsCOMArray<msgIAddressObject> recipients;
finalHeaders->GetAddressingHeader("To", recipients);
hasDisclosedRecipient |= !recipients.IsEmpty();
finalHeaders->GetAddressingHeader("Cc", recipients);
hasDisclosedRecipient |= !recipients.IsEmpty();
// If we don't have disclosed recipient (only Bcc), address the message to
// undisclosed-recipients to prevent problem with some servers
@ -591,8 +546,9 @@ mime_generate_headers (nsMsgCompFields *fields,
prefs->GetBoolPref("mail.compose.add_undisclosed_recipients", &bAddUndisclosedRecipients);
if (bAddUndisclosedRecipients)
{
const char* pBcc = fields->GetBcc(); //Do not free me!
if (pBcc && *pBcc)
bool hasBcc = false;
fields->HasHeader("Bcc", &hasBcc);
if (hasBcc)
{
nsCOMPtr<nsIStringBundleService> stringService =
mozilla::services::GetStringBundleService();
@ -607,17 +563,24 @@ mime_generate_headers (nsMsgCompFields *fields,
getter_Copies(undisclosedRecipients));
if (NS_SUCCEEDED(rv) && !undisclosedRecipients.IsEmpty())
{
PUSH_STRING("To: ");
PUSH_STRING(NS_LossyConvertUTF16toASCII(undisclosedRecipients).get());
PUSH_STRING(":;");
PUSH_NEWLINE ();
}
nsCOMPtr<nsIMsgHeaderParser> headerParser(
mozilla::services::GetHeaderParser());
nsCOMPtr<msgIAddressObject> group;
headerParser->MakeGroupObject(undisclosedRecipients,
nullptr, 0, getter_AddRefs(group));
recipients.AppendElement(group);
finalHeaders->SetAddressingHeader("To", recipients);
}
}
}
}
}
}
// We don't want to emit a Bcc header to the output. If we are saving this to
// Drafts/Sent, this is readded later in nsMsgSend.cpp.
finalHeaders->DeleteHeader("bcc");
// Skip no or empty priority.
nsAutoCString priority;
rv = fields->GetRawHeader("X-Priority", priority);

Просмотреть файл

@ -496,7 +496,7 @@ function* testSentMessage() {
});
yield sendMessage({"bcc": "Somebody <test@tinderbox.invalid"}, identity);
checkMessageHeaders(daemon.post, {
"To": "undisclosed-recipients:;"
"To": "undisclosed-recipients: ;"
});
yield sendMessage({
"to": "Somebody <test@tinderbox.invalid>",

Просмотреть файл

@ -39,6 +39,25 @@ StringEnumerator.prototype = {
}
};
/**
* If we get XPConnect-wrapped objects for msgIAddressObjects, we will have
* properties defined for 'group' that throws off jsmime. This function converts
* the addresses into the form that jsmime expects.
*/
function fixXpconnectAddresses(addrs) {
return addrs.map((addr) => {
// This is ideally !addr.group, but that causes a JS strict warning, if
// group is not in addr, since that's enabled in all chrome code now.
if (!('group' in addr) || addr.group === undefined || addr.group === null) {
return MimeAddressParser.prototype.makeMailboxObject(addr.name,
addr.email);
} else {
return MimeAddressParser.prototype.makeGroupObject(addr.name,
fixXpconnectAddresses(addr.group));
}
});
}
/**
* This is a base handler for supporting msgIStructuredHeaders, since we have
* two implementations that need the readable aspects of the interface.
@ -171,7 +190,7 @@ MimeWritableStructuredHeaders.prototype = {
},
setAddressingHeader: function (aHeaderName, aAddresses, aCount) {
this.setHeader(aHeaderName, aAddresses);
this.setHeader(aHeaderName, fixXpconnectAddresses(aAddresses));
},
setRawHeader: function (aHeaderName, aValue, aCharset) {
@ -252,6 +271,7 @@ MimeAddressParser.prototype = {
},
makeMimeHeader: function (addresses, length) {
addresses = fixXpconnectAddresses(addresses);
// Don't output any necessary continuations, so make line length as large as
// possible first.
let options = {
@ -322,7 +342,7 @@ MimeAddressParser.prototype = {
makeGroupObject: function (aName, aMembers) {
let object = Object.create(EmailGroup);
object.name = aName;
object.members = aMembers;
object.group = aMembers;
return object;
},