diff options
Diffstat (limited to 'mailnews/compose/src/nsMsgSend.h')
-rw-r--r-- | mailnews/compose/src/nsMsgSend.h | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/mailnews/compose/src/nsMsgSend.h b/mailnews/compose/src/nsMsgSend.h new file mode 100644 index 000000000..558c8e53e --- /dev/null +++ b/mailnews/compose/src/nsMsgSend.h @@ -0,0 +1,405 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __MSGSEND_H__ +#define __MSGSEND_H__ + +/* Asynchronous mailing of messages with attached URLs. + + - If there are any attachments, start their URLs going, and write each + of them to a temp file. + + - While writing to their files, examine the data going by and decide + what kind of encoding, if any, they need. Also remember their content + types. + + - Once that URLs has been saved to a temp file (or, if there were no + attachments) generate a final temp file, of the actual message: + + - Generate a string of the headers. + - Open the final temp file. + - Write the headers. + - Examine the first part, and decide whether to encode it. + - Write the first part to the file, possibly encoded. + - Write the second and subsequent parts to the file, possibly encoded. + (Open the first temp file and copy it to the final temp file, and so + on, through an encoding filter.) + + - Delete the attachment temp file(s) as we finish with them. + - Close the final temp file. + - Open the news: url. + - Send the final temp file to NNTP. + If there's an error, run the callback with "failure" status. + - If mail succeeded, open the mailto: url. + - Send the final temp file to SMTP. + If there's an error, run the callback with "failure" status. + - Otherwise, run the callback with "success" status. + - Free everything, delete the final temp file. + + The theory behind the encoding logic: + ===================================== + + If the document is of type text/html, and the user has asked to attach it + as source or postscript, it will be run through the appropriate converter + (which will result in a document of type text/plain.) + + An attachment will be encoded if: + + - it is of a non-text type (in which case we will use base64); or + - The "use QP" option has been selected and high-bit characters exist; or + - any NULLs exist in the document; or + - any line is longer than 990 bytes (see LINELENGTH_ENCODING_THRESHOLD below) + and it is not of type message/rfc822. + + - If we are encoding, and more than 10% of the document consists of + non-ASCII characters, then we always use base64 instead of QP. + + We eschew quoted-printable in favor of base64 for documents which are likely + to always be binary (images, sound) because, on the off chance that a GIF + file (for example) might contain primarily bytes in the ASCII range, using + the quoted-printable representation might cause corruption due to the + translation of CR or LF to CRLF. So, when we don't know that the document + has "lines", we don't use quoted-printable. + */ + +/* For maximal compatibility, it helps to emit both + Content-Type: <type>; name="<original-file-name>" + as well as + Content-Disposition: inline; filename="<original-file-name>" + + The lossage here is, RFC1341 defined the "name" parameter to Content-Type, + but then RFC1521 deprecated it in anticipation of RFC1806, which defines + Content-Type and the "filename" parameter. But, RFC1521 is "Standards Track" + while RFC1806 is still "Experimental." So, it's probably best to just + implement both. + */ +#define EMIT_NAME_IN_CONTENT_TYPE + +/* Whether the contents of the BCC header should be preserved in the FCC'ed + copy of a message. See comments below, in mime_do_fcc_1(). + */ +#define SAVE_BCC_IN_FCC_FILE + +/* When attaching an HTML document, one must indicate the original URL of + that document, if the receiver is to have any chance of being able to + retreive and display the inline images, or to click on any links in the + HTML. + + The way we have done this in the past is by inserting a <BASE> tag as the + first line of all HTML documents we attach. (This is kind of bad in that + we're actually modifying the document, and it really isn't our place to + do that.) + + The sanctioned *new* way of doing this is to insert a Content-Base header + field on the attachment. This is (will be) a part of the forthcoming MHTML + spec. + + If GENERATE_CONTENT_BASE, we generate a Content-Base header. + + We used to have a MANGLE_HTML_ATTACHMENTS_WITH_BASE_TAG symbol that we + defined, which added a BASE tag to the bodies. We stopped doing this in + 4.0. */ +#define GENERATE_CONTENT_BASE + + +// +// Necessary includes +// +#include "nsCOMPtr.h" +#include "nsIMsgSend.h" +#include "nsIStringBundle.h" +#include "msgCore.h" +#include "prprf.h" +#include "nsIOutputStream.h" +#include "nsMsgMessageFlags.h" +#include "nsIURL.h" +#include "nsMsgAttachmentHandler.h" +#include "nsMsgCompFields.h" +#include "nsIMsgSendListener.h" +#include "nsIDOMNode.h" +#include "nsIEditor.h" +#include "nsIUrlListener.h" +#include "nsIMsgStatusFeedback.h" +#include "nsIMsgIdentity.h" +#include "nsIMsgHdr.h" +#include "nsIMsgIdentity.h" +#include "nsWeakReference.h" +#include "nsPIDOMWindow.h" +#include "nsIDOMWindow.h" +#include "nsIMsgComposeSecure.h" +#include "nsAutoPtr.h" +#include "nsMsgAttachmentData.h" +#include "nsIMsgFilterService.h" +#include "nsIMsgOperationListener.h" + +// +// Some necessary defines... +// +#define MIME_BUFFER_SIZE 4096 // must be greater than 1000 + // SMTP (RFC821) limit +// Maximum number of bytes we allow in a line before we force +// encoding to base64 if not already QR-encoded or of type message/rfc822. +#define LINELENGTH_ENCODING_THRESHOLD 990 + +// +// Utilities for string handling +// +#define PUSH_STRING(S) \ + do { PL_strcpy (buffer_tail, S); buffer_tail += PL_strlen (S); } while(0) +#define PUSH_STRINGN(S,N) \ + do { memcpy(buffer_tail, (S), (N)); buffer_tail += (N); } while(0) +#define PUSH_NEWLINE() \ + do { *buffer_tail++ = '\r'; *buffer_tail++ = '\n'; *buffer_tail = '\0'; } while(0) + +// +// Forward declarations... +// +class nsMsgSendPart; +class nsMsgCopy; +class nsIPrompt; +class nsIInterfaceRequestor; + +namespace mozilla { +namespace mailnews { +class MimeEncoder; +} +} + +class nsMsgComposeAndSend : public nsIMsgSend, + public nsIMsgOperationListener, + public nsSupportsWeakReference +{ + typedef mozilla::mailnews::MimeEncoder MimeEncoder; +public: + // + // Define QueryInterface, AddRef and Release for this class + // + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIMSGSEND + NS_DECL_NSIMSGOPERATIONLISTENER + + nsMsgComposeAndSend(); + + + // Delivery and completion callback routines... + NS_IMETHOD DeliverMessage(); + NS_IMETHOD DeliverFileAsMail(); + NS_IMETHOD DeliverFileAsNews(); + void DoDeliveryExitProcessing(nsIURI * aUrl, nsresult aExitCode, bool aCheckForMail); + nsresult FormatStringWithSMTPHostNameByName(const char16_t* aMsgName, char16_t **aString); + + nsresult DoFcc(); + nsresult StartMessageCopyOperation(nsIFile *aFileSpec, + nsMsgDeliverMode mode, + const nsCString& dest_uri); + + + nsresult SendToMagicFolder(nsMsgDeliverMode flag); + + // Check to see if it's ok to save msgs to the configured folder. + bool CanSaveMessagesToFolder(const char *folderURL); + + // + // FCC operations... + // + nsresult MimeDoFCC (nsIFile *input_file, + nsMsgDeliverMode mode, + const char *bcc_header, + const char *fcc_header, + const char *news_url); + + // Init() will allow for either message creation without delivery or full + // message creation and send operations + // + nsresult Init( + nsIMsgIdentity *aUserIdentity, + const char *aAccountKey, + nsMsgCompFields *fields, + nsIFile *sendFile, + bool digest_p, + bool dont_deliver_p, + nsMsgDeliverMode mode, + nsIMsgDBHdr *msgToReplace, + const char *attachment1_type, + const nsACString &attachment1_body, + nsIArray *attachments, + nsIArray *preloaded_attachments, + const char *password, + const nsACString &aOriginalMsgURI, + MSG_ComposeType aType); + + // + // Setup the composition fields + // + nsresult InitCompositionFields(nsMsgCompFields *fields, + const nsACString &aOriginalMsgURI, + MSG_ComposeType aType); + + NS_IMETHOD GetBodyFromEditor(); + + + // + // Attachment processing... + // + nsresult HackAttachments(nsIArray *attachments, + nsIArray *preloaded_attachments); + nsresult CountCompFieldAttachments(); + nsresult AddCompFieldLocalAttachments(); + nsresult AddCompFieldRemoteAttachments(uint32_t aStartLocation, int32_t *aMailboxCount, int32_t *aNewsCount); + + // Deal with multipart related data + nsresult ProcessMultipartRelated(int32_t *aMailboxCount, int32_t *aNewsCount); + nsresult GetEmbeddedObjectInfo(nsIDOMNode *node, nsMsgAttachmentData *attachment, bool *acceptObject); + uint32_t GetMultipartRelatedCount(bool forceToBeCalculated = false); + nsCOMPtr<nsIArray> mEmbeddedObjectList; // it's initialized when calling GetMultipartRelatedCount + + // Body processing + nsresult SnarfAndCopyBody(const nsACString &attachment1_body, + const char *attachment1_type); + + int32_t PreProcessPart(nsMsgAttachmentHandler *ma, + nsMsgSendPart *toppart); // The very top most container of the message + // For part processing + + nsresult SetStatusMessage(const nsString &aMsgString); // Status message method + + // + // All vars necessary for this implementation + // + nsMsgKey m_messageKey; // jt -- Draft/Template support; newly created key + nsCOMPtr<nsIMsgIdentity> mUserIdentity; + nsCString mAccountKey; + RefPtr<nsMsgCompFields> mCompFields; // All needed composition fields (header, etc...) + nsCOMPtr<nsIFile> mTempFile; // our temporary file + + nsCOMPtr<nsIOutputStream> mOutputFile; // the actual output file stream + uint32_t mMessageWarningSize; // Warn if a message is over this size! + + bool m_dont_deliver_p; // If set, we just return the nsIFile of the file + // created, instead of actually delivering message. + nsMsgDeliverMode m_deliver_mode; // nsMsgDeliverNow, nsMsgQueueForLater, nsMsgSaveAsDraft, + // nsMsgSaveAsTemplate and nsMsgSendUnsent + nsCOMPtr<nsIMsgDBHdr> mMsgToReplace; // If the mode is nsMsgSaveAsDraft, this is the message it will + // replace + nsString mSavedToFolderName; // Name of folder we're saving to, used when + // displaying error on save. + // These are needed for callbacks to the FE... + nsCOMPtr<nsPIDOMWindowOuter> mParentWindow; + nsCOMPtr<nsIMsgProgress> mSendProgress; + nsCOMPtr<nsIMsgSendListener> mListener; + nsCOMPtr<nsIMsgStatusFeedback> mStatusFeedback; + nsCOMPtr<nsIRequest> mRunningRequest; + bool mSendMailAlso; + nsCOMPtr<nsIFile> mReturnFile; // a holder for file spec's to be returned to caller + + // File where we stored our HTML so that we could make the plaintext form. + nsCOMPtr<nsIFile> mHTMLFile; + + // Variable for storing the draft name; + nsCString m_folderName; + + // mapping between editor dom node indexes and saved mime part numbers. + nsTArray<nsCString> m_partNumbers; + // + // These variables are needed for message Copy operations! + // + nsCOMPtr<nsIFile> mCopyFile; + nsCOMPtr<nsIFile> mCopyFile2; + RefPtr<nsMsgCopy> mCopyObj; + bool mNeedToPerformSecondFCC; + bool mPerformingSecondFCC; + + // For MHTML message creation + nsCOMPtr<nsIEditor> mEditor; + + // + // The first attachment, if any (typed in by the user.) + // + char *m_attachment1_type; + char *m_attachment1_encoding; + nsAutoPtr<MimeEncoder> m_attachment1_encoder; + char *m_attachment1_body; + uint32_t m_attachment1_body_length; + char *mOriginalHTMLBody; + + // The plaintext form of the first attachment, if needed. + RefPtr<nsMsgAttachmentHandler> m_plaintext; + + // The multipart/related save object for HTML text. + nsMsgSendPart *m_related_part; + nsMsgSendPart *m_related_body_part; + + // + // Subsequent attachments, if any. + // + uint32_t m_attachment_count; + uint32_t m_attachment_pending_count; + nsTArray< RefPtr<nsMsgAttachmentHandler> > m_attachments; + nsresult m_status; // in case some attachments fail but not all + + uint32_t mPreloadedAttachmentCount; + uint32_t mRemoteAttachmentCount; + int32_t mMultipartRelatedAttachmentCount; // the number of mpart related attachments, -1 means it has not been yet initialized + + uint32_t mCompFieldLocalAttachments; // the number of file:// attachments in the comp fields + uint32_t mCompFieldRemoteAttachments; // the number of remote attachments in the comp fields + + // + // attachment states and other info... + // + bool m_pre_snarfed_attachments_p; // If true, then the attachments were + // loaded by in the background and therefore + // we shouldn't delete the tmp files (but should + // leave that to the caller.) + + bool m_digest_p; // Whether to be multipart/digest instead of + // multipart/mixed. + + bool m_be_synchronous_p; // If true, we will load one URL after another, + // rather than starting all URLs going at once + // and letting them load in parallel. This is + // more efficient if (for example) all URLs are + // known to be coming from the same news server + // or mailbox: loading them in parallel would + // cause multiple connections to the news + // server to be opened, or would cause much seek()ing. + + bool mGUINotificationEnabled; // Should we throw up the GUI alerts on errors? + bool mAbortInProcess; // Used by Abort to avoid reentrance. + + nsCOMPtr<nsIMsgComposeSecure> m_crypto_closure; + +protected: + nsCOMPtr<nsIStringBundle> mComposeBundle; + nsresult GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks); + + virtual ~nsMsgComposeAndSend(); + nsresult FilterSentMessage(); + nsresult MaybePerformSecondFCC(nsresult aStatus); + + // generates a message id for our message, if necessary + void GenerateMessageId( ); + + // add default custom headers to the message + nsresult AddDefaultCustomHeaders(); + + // add Mail-Followup-To and Mail-Reply-To header + nsresult AddMailFollowupToHeader(); + nsresult AddMailReplyToHeader(); + nsresult AddXForwardedMessageIdHeader(); + + nsCOMPtr<nsIMsgSendReport> mSendReport; + nsCString mSmtpPassword; // store the smtp Password use during a send +}; + +// +// These C routines should only be used by the nsMsgSendPart class. +// +extern nsresult mime_write_message_body(nsIMsgSend *state, const char *buf, uint32_t size); +extern char *mime_get_stream_write_buffer(void); +extern nsresult mime_encoder_output_fn (const char *buf, int32_t size, void *closure); +extern bool UseQuotedPrintable(void); + +#endif /* __MSGSEND_H__ */ |