Back to index

lightning-sunbird  0.9+nobinonly
nsMsgSend.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef __MSGSEND_H__
00039 #define __MSGSEND_H__
00040 
00041 /* Asynchronous mailing of messages with attached URLs.
00042 
00043    - If there are any attachments, start their URLs going, and write each
00044      of them to a temp file.
00045 
00046    - While writing to their files, examine the data going by and decide
00047      what kind of encoding, if any, they need.  Also remember their content
00048      types.
00049 
00050    - Once that URLs has been saved to a temp file (or, if there were no
00051      attachments) generate a final temp file, of the actual message:
00052 
00053         -  Generate a string of the headers.
00054         -  Open the final temp file.
00055         -  Write the headers.
00056      -  Examine the first part, and decide whether to encode it.
00057         -  Write the first part to the file, possibly encoded.
00058         -  Write the second and subsequent parts to the file, possibly encoded.
00059         (Open the first temp file and copy it to the final temp file, and so
00060                    on, through an encoding filter.)
00061 
00062    - Delete the attachment temp file(s) as we finish with them.
00063         - Close the final temp file.
00064         - Open the news: url.
00065         - Send the final temp file to NNTP.
00066           If there's an error, run the callback with "failure" status.
00067         - If mail succeeded, open the mailto: url.
00068         - Send the final temp file to SMTP.
00069           If there's an error, run the callback with "failure" status.
00070         - Otherwise, run the callback with "success" status.
00071         - Free everything, delete the final temp file.
00072 
00073   The theory behind the encoding logic:
00074   =====================================
00075 
00076   If the document is of type text/html, and the user has asked to attach it
00077   as source or postscript, it will be run through the appropriate converter
00078   (which will result in a document of type text/plain.)
00079 
00080   An attachment will be encoded if:
00081 
00082    - it is of a non-text type (in which case we will use base64); or
00083    - The "use QP" option has been selected and high-bit characters exist; or
00084    - any NULLs exist in the document; or
00085    - any line is longer than 900 bytes.
00086 
00087    - If we are encoding, and more than 10% of the document consists of
00088      non-ASCII characters, then we always use base64 instead of QP.
00089 
00090   We eschew quoted-printable in favor of base64 for documents which are likely
00091   to always be binary (images, sound) because, on the off chance that a GIF
00092   file (for example) might contain primarily bytes in the ASCII range, using
00093   the quoted-printable representation might cause corruption due to the
00094   translation of CR or LF to CRLF.  So, when we don't know that the document
00095   has "lines", we don't use quoted-printable.
00096  */
00097 
00098 /* For maximal compatibility, it helps to emit both
00099       Content-Type: <type>; name="<original-file-name>"
00100    as well as
00101       Content-Disposition: inline; filename="<original-file-name>"
00102 
00103   The lossage here is, RFC1341 defined the "name" parameter to Content-Type,
00104   but then RFC1521 deprecated it in anticipation of RFC1806, which defines
00105   Content-Type and the "filename" parameter.  But, RFC1521 is "Standards Track"
00106   while RFC1806 is still "Experimental."  So, it's probably best to just
00107   implement both.
00108  */
00109 #define EMIT_NAME_IN_CONTENT_TYPE
00110 
00111 /* Whether the contents of the BCC header should be preserved in the FCC'ed
00112    copy of a message.  See comments below, in mime_do_fcc_1().
00113  */
00114 #define SAVE_BCC_IN_FCC_FILE
00115 
00116 /* When attaching an HTML document, one must indicate the original URL of
00117    that document, if the receiver is to have any chance of being able to
00118    retreive and display the inline images, or to click on any links in the
00119    HTML.
00120 
00121    The way we have done this in the past is by inserting a <BASE> tag as the
00122    first line of all HTML documents we attach.  (This is kind of bad in that
00123    we're actually modifying the document, and it really isn't our place to
00124    do that.)
00125 
00126    The sanctioned *new* way of doing this is to insert a Content-Base header
00127    field on the attachment.  This is (will be) a part of the forthcoming MHTML
00128    spec.
00129 
00130    If GENERATE_CONTENT_BASE, we generate a Content-Base header.
00131 
00132    We used to have a MANGLE_HTML_ATTACHMENTS_WITH_BASE_TAG symbol that we
00133    defined, which added a BASE tag to the bodies.  We stopped doing this in
00134    4.0.  */
00135 #define GENERATE_CONTENT_BASE
00136 
00137 
00138 //
00139 // Necessary includes
00140 //
00141 #include "nsIMsgSend.h"
00142 
00143 #include "msgCore.h"
00144 #include "prprf.h" 
00145 #include "nsFileStream.h"
00146 #include "nsMsgMessageFlags.h"
00147 #include "nsIURL.h"
00148 #include "nsMsgAttachmentHandler.h"
00149 #include "nsMsgCompFields.h"
00150 #include "nsIMsgSendListener.h"
00151 #include "nsIDOMNode.h"
00152 #include "nsIEditor.h"
00153 #include "nsIUrlListener.h"
00154 #include "nsIMsgStatusFeedback.h"
00155 #include "nsIMsgStringService.h"
00156 #include "nsIMsgIdentity.h"
00157 #include "nsIMsgHdr.h"
00158 #include "nsIMsgIdentity.h"
00159 #include "nsWeakReference.h"
00160 #include "nsIDOMWindowInternal.h"
00161 #include "nsIMsgComposeSecure.h"
00162 
00163 //
00164 // Some necessary defines...
00165 //
00166 #define TEN_K                 10240
00167 #define MIME_BUFFER_SIZE      4096 // must be greater than 1000
00168                                    // SMTP (RFC821) limit
00169 
00170 //
00171 // Utilities for string handling
00172 //
00173 #define PUSH_STRING(S) \
00174  do { PL_strcpy (buffer_tail, S); buffer_tail += PL_strlen (S); } while(0)
00175 #define PUSH_STRINGN(S,N) \
00176  do { memcpy(buffer_tail, (S), (N)); buffer_tail += (N); } while(0)
00177 #define PUSH_NEWLINE() \
00178  do { *buffer_tail++ = nsCRT::CR; *buffer_tail++ = nsCRT::LF; *buffer_tail = '\0'; } while(0)
00179 
00180 //
00181 // Forward declarations...
00182 //
00183 class nsMsgSendPart;
00184 class nsMsgCopy;
00185 class nsMsgDeliveryListener;
00186 class nsIPrompt;
00187 class nsIInterfaceRequestor;
00188 
00189 class nsMsgComposeAndSend : public nsIMsgSend
00190 {
00191 public:
00192   //
00193   // The exit method used when downloading attachments only.
00194   // This still may be useful because of the fact that it is an
00195   // internal callback only. This way, no thread boundry issues and
00196   // we can get away without all of the listener array code.
00197   //
00198   void (*m_attachments_done_callback) (nsresult  status, 
00199         const PRUnichar *error_msg, struct nsMsgAttachedFile *attachments);
00200   
00201   //
00202   // Define QueryInterface, AddRef and Release for this class 
00203   //
00204   NS_DECL_ISUPPORTS
00205 
00206   nsMsgComposeAndSend();
00207   virtual     ~nsMsgComposeAndSend();
00208 
00209 
00210   // Delivery and completion callback routines...
00211   NS_IMETHOD  DeliverMessage();
00212   NS_IMETHOD  DeliverFileAsMail();
00213   NS_IMETHOD  DeliverFileAsNews();
00214   void        DoDeliveryExitProcessing(nsIURI * aUrl, nsresult aExitCode, PRBool aCheckForMail);
00215   nsresult    FormatStringWithSMTPHostNameByID(PRInt32 aMsgId, PRUnichar **aString);
00216 
00217   nsresult    DoFcc();
00218   nsresult    StartMessageCopyOperation(nsIFileSpec        *aFileSpec, 
00219                                         nsMsgDeliverMode   mode,
00220                                         char                      *dest_uri);
00221 
00222   void       Clear();
00223 
00224   NS_METHOD   SendToMagicFolder (nsMsgDeliverMode flag);
00225   nsresult    QueueForLater();
00226   nsresult    SaveAsDraft();
00227   nsresult    SaveInSentFolder();
00228   nsresult    SaveAsTemplate();
00229 
00230   // Check to see if it's ok to save msgs to the configured folder.
00231   PRBool CanSaveMessagesToFolder(const char *folderURL);
00232 
00233   //
00234   // FCC operations...
00235   //
00236   nsresult    MimeDoFCC (nsFileSpec *input_file,  
00237     nsMsgDeliverMode mode,
00238     const char *bcc_header,
00239     const char *fcc_header,
00240     const char *news_url);
00241   
00242   // Init() will allow for either message creation without delivery or full
00243   // message creation and send operations
00244   //
00245   nsresult    Init(
00246                    nsIMsgIdentity   *aUserIdentity,
00247                    const char       *aAccountKey,
00248                    nsMsgCompFields  *fields,
00249                    nsFileSpec       *sendFileSpec,
00250                    PRBool           digest_p,
00251                    PRBool           dont_deliver_p,
00252                    nsMsgDeliverMode mode,
00253                    nsIMsgDBHdr      *msgToReplace,
00254                    const char       *attachment1_type,
00255                    const char       *attachment1_body,
00256                    PRUint32         attachment1_body_length,
00257                    const nsMsgAttachmentData   *attachments,
00258                    const nsMsgAttachedFile     *preloaded_attachments,
00259                    const char       *password,
00260                    const nsACString &aOriginalMsgURI,
00261                    MSG_ComposeType  aType);
00262 
00263   //
00264   // Setup the composition fields
00265   //
00266   nsresult    InitCompositionFields(nsMsgCompFields *fields,
00267                                     const nsACString &aOriginalMsgURI,
00268                                     MSG_ComposeType aType);
00269 
00270   int         SetMimeHeader(nsMsgCompFields::MsgHeaderID header, const char *value);
00271   NS_IMETHOD  GetBodyFromEditor();
00272 
00273 
00274   //
00275   // Attachment processing...
00276   //
00277   nsresult    HackAttachments(const struct nsMsgAttachmentData *attachments,
00278                                                        const struct nsMsgAttachedFile *preloaded_attachments);
00279   nsresult    CountCompFieldAttachments();
00280   nsresult    AddCompFieldLocalAttachments();
00281   nsresult    AddCompFieldRemoteAttachments(PRUint32  aStartLocation, PRInt32 *aMailboxCount, PRInt32 *aNewsCount);
00282 
00283   // Deal with multipart related data
00284   nsresult    ProcessMultipartRelated(PRInt32 *aMailboxCount, PRInt32 *aNewsCount); 
00285   nsresult    GetEmbeddedObjectInfo(nsIDOMNode *node, nsMsgAttachmentData *attachment, PRBool *acceptObject);
00286   PRUint32    GetMultipartRelatedCount(PRBool forceToBeCalculated = PR_FALSE);
00287   nsCOMPtr<nsISupportsArray> mEmbeddedObjectList; // it's initialized when calling GetMultipartRelatedCount
00288 
00289   // Body processing
00290   nsresult    SnarfAndCopyBody(const char  *attachment1_body,
00291                                                              PRUint32    attachment1_body_length,
00292                                const char  *attachment1_type);
00293 
00294   PRInt32     PreProcessPart(nsMsgAttachmentHandler  *ma,
00295                              nsMsgSendPart           *toppart); // The very top most container of the message
00296                                                                 // For part processing
00297 
00298   NS_DECL_NSIMSGSEND
00299   nsresult    SetStatusMessage(const PRUnichar *aMsgString);     // Status message method
00300   
00301   //
00302   // All vars necessary for this implementation
00303   //
00304   nsMsgKey                  m_messageKey;        // jt -- Draft/Template support; newly created key
00305   nsCOMPtr<nsIMsgIdentity>  mUserIdentity;
00306   nsCString                 mAccountKey;
00307   nsCOMPtr<nsMsgCompFields> mCompFields;         // All needed composition fields (header, etc...)
00308   nsFileSpec                *mTempFileSpec;      // our temporary file
00309   
00310   nsOutputFileStream        *mOutputFile;        // the actual output file stream
00311   PRUint32                  mMessageWarningSize; // Warn if a message is over this size!
00312 
00313   PRBool                    m_dont_deliver_p;    // If set, we just return the nsFileSpec of the file
00314                                                                                     // created, instead of actually delivering message.
00315   nsMsgDeliverMode          m_deliver_mode;      // nsMsgDeliverNow, nsMsgQueueForLater, nsMsgSaveAsDraft, 
00316                                                  // nsMsgSaveAsTemplate and nsMsgSendUnsent
00317   nsCOMPtr<nsIMsgDBHdr>     mMsgToReplace;       // If the mode is nsMsgSaveAsDraft, this is the message it will
00318                                                  // replace
00319 
00320   // These are needed for callbacks to the FE...
00321   nsCOMPtr<nsIDOMWindowInternal>  mParentWindow;
00322   nsCOMPtr<nsIMsgProgress>        mSendProgress;
00323   nsCOMPtr<nsIMsgSendListener>    mListener;
00324   nsCOMPtr<nsIMsgStatusFeedback>  mStatusFeedback;
00325   nsCOMPtr<nsIRequest>      mRunningRequest;
00326   PRBool                    mSendMailAlso;
00327   nsIFileSpec               *mReturnFileSpec;     // a holder for file spec's to be returned to caller
00328 
00329   // File where we stored our HTML so that we could make the plaintext form.
00330   nsFileSpec                *mHTMLFileSpec;
00331 
00332   // Variable for storing the draft name;
00333   nsCString                  m_folderName;
00334   //
00335   // These variables are needed for message Copy operations!
00336   //
00337   nsIFileSpec               *mCopyFileSpec;
00338   nsIFileSpec               *mCopyFileSpec2;
00339   nsMsgCopy                 *mCopyObj;
00340   PRBool                    mNeedToPerformSecondFCC;
00341 
00342   // For MHTML message creation
00343   nsCOMPtr<nsIEditor>       mEditor;
00344 
00345   //
00346   // The first attachment, if any (typed in by the user.)
00347   //
00348   char                    *m_attachment1_type;
00349   char                    *m_attachment1_encoding;
00350   MimeEncoderData         *m_attachment1_encoder_data;
00351   char                    *m_attachment1_body;
00352   PRUint32                m_attachment1_body_length;
00353   char                    *mOriginalHTMLBody;
00354 
00355   // The plaintext form of the first attachment, if needed.
00356   nsMsgAttachmentHandler  *m_plaintext;
00357 
00358        // The multipart/related save object for HTML text.
00359   nsMsgSendPart           *m_related_part;
00360   nsMsgSendPart           *m_related_body_part;
00361 
00362   //
00363   // Subsequent attachments, if any.
00364   //
00365   PRUint32                m_attachment_count;
00366   PRUint32                m_attachment_pending_count;
00367   nsMsgAttachmentHandler  *m_attachments;
00368   nsresult                m_status; // in case some attachments fail but not all 
00369 
00370   PRUint32                mPreloadedAttachmentCount;
00371   PRUint32                mRemoteAttachmentCount;
00372   PRInt32                 mMultipartRelatedAttachmentCount; // the number of mpart related attachments, -1 means it has not been yet initialized
00373 
00374   PRUint32                mCompFieldLocalAttachments;     // the number of file:// attachments in the comp fields
00375   PRUint32                mCompFieldRemoteAttachments;    // the number of remote attachments in the comp fields
00376 
00377   //
00378   // attachment states and other info...
00379   //
00380   PRBool                  m_attachments_only_p;         // If set, then we don't construct a complete
00381                                                                                                 // MIME message; instead, we just retrieve the
00382                                                                                                 // attachments from the network, store them in
00383                                                                                                 // tmp files, and return a list of
00384                                                                                                 // nsMsgAttachedFile structs which describe them.
00385 
00386   PRBool                  m_pre_snarfed_attachments_p;  // If true, then the attachments were
00387                                                                                                           // loaded by in the background and therefore 
00388                                                         // we shouldn't delete the tmp files (but should 
00389                                                         // leave that to the caller.)
00390 
00391   PRBool                  m_digest_p;                   // Whether to be multipart/digest instead of
00392                                                                                                 // multipart/mixed. 
00393 
00394   PRBool                  m_be_synchronous_p;              // If true, we will load one URL after another,
00395                                                                                                 // rather than starting all URLs going at once
00396                                                                                                 // and letting them load in parallel.  This is
00397                                                                                                 // more efficient if (for example) all URLs are
00398                                                                                                 // known to be coming from the same news server
00399                                                                                                 // or mailbox: loading them in parallel would
00400                                                                                                 // cause multiple connections to the news
00401                                                                                                 // server to be opened, or would cause much seek()ing.
00402 
00403   PRBool                  mGUINotificationEnabled;      // Should we throw up the GUI alerts on errors?
00404   PRBool                  mLastErrorReported;           // Last error reported to the user.
00405   PRBool                  mAbortInProcess;              // Used by Abort to avoid reentrance.
00406 
00407   nsCOMPtr<nsIMsgComposeSecure> m_crypto_closure;
00408 
00409 protected:
00410   nsCOMPtr<nsIMsgStringService> mComposeBundle;
00411   nsresult GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks);
00412 private:
00413   // will set m_attachment1_body & m_attachment1_body_length;
00414   nsresult EnsureLineBreaks(const char *body, PRUint32 body_len);
00415 
00416   // generates a message id for our message, if necessary
00417   void GenerateMessageId( );
00418 
00419   // add default custom headers to the message
00420   nsresult AddDefaultCustomHeaders();
00421   
00422   nsCOMPtr<nsIMsgSendReport>  mSendReport;
00423   nsCString                   mSmtpPassword;            // store the smtp Password use during a send
00424 };
00425 
00426 // 
00427 // These C routines should only be used by the nsMsgSendPart class.
00428 //
00429 extern nsresult mime_write_message_body(nsIMsgSend *state, char *buf, PRInt32 size);
00430 extern char   *mime_get_stream_write_buffer(void);
00431 extern nsresult PR_CALLBACK mime_encoder_output_fn (const char *buf, PRInt32 size, void *closure);
00432 extern PRBool UseQuotedPrintable(void);
00433 
00434 #endif /*  __MSGSEND_H__ */