Mail composition back end

Warning: The content of this article may be out of date. It was imported from mozilla.org and last updated in 2000.


by Richard H. Pizzarro <rhp@netscape.com> Contents

Overview

I've done considerable work in the past few weeks reorganizing the Mail Composition back end, so I thought it would be helpful to put together a small doc on the new interfaces and how one can use them. The Mail Composition back end is responsible for the assembly and creation of RFC822 messages to be delivered either via SMTP or NNTP services. You also have the ability to save RFC822 files to disk, should you need this data for some reason. Included in this functionality is the code to copy the messages to the appropriate locations after delivery (i.e. a "Sent" folder) as well as the ability to store messages for features like "Drafts" and "Templates". Several (but not all) of these interfaces are specified in IDL. This will change in the coming weeks and allow for developers to write JavaScript to take advantage of the back end services. Also, I will talk about some features though they may not be complete as of yet. I will try to make comments for these exceptions.

Sending Messages

The primary responsibility of the back end is for the creation and sending of RFC822 messages. The interface that accomplishes this task is the nsIMsgSend interface. The feedback mechanism is provided by a nsIMsgSendListener which is implemented by the caller. The caller has the ability to add or remove listener interfaces to the nsIMsgSend object and the interface can support multiple listeners. (For detailed information on the listener interfaces, see the Listener Interfaces section of this document)

nsIMsgSend

The following describes the methods of the nsIMsgSend interface. All of these methods are asynchronous operations.

CreateAndSendMessage

The CreateAndSendMessage method will create an RFC822 message and send it all in one operation as well as providing the ability to save disk files for later use. The mode of delivery can also be specified for the "Send Later", "Drafts" and "Templates" operations. (NOTE: This method could easily be broken in to a few different calls. Currently, this method does several functions depending on the arguments passed in, but this could easily lead to confusion. This is something that very well may change as time allows).

NS_IMETHOD CreateAndSendMessage(
nsIEditorShell *aEditor,
- the editor object for the mail compose operation. If this is not null, the body will be extracted from this object and any embedded objects or links will be sent as part of the message in MHTML
nsIMsgIdentity *aUserIdentity,
- the user identity for the person doing the send operation. This will be needed to determine the appropriate folder for copy operations.
nsIMsgCompFields *fields,
- the message composition fields. This will contain all of the relevant header information for message creation
PRBool digest_p,
- this is a flag that says that most of the documents we are attaching are themselves messages, and so we should generate a multipart/digest container instead of multipart/mixed. (It's a minor difference.)
PRBool dont_deliver_p,
- If "dont_deliver_p" is false, then we actually deliver the message to the SMTP and/or NNTP server
nsMsgDeliverMode mode,
- mode is the delivery mode. This can be set for the various modes of delivery. These can include nsMsgDeliverNow, nsMsgQueueForLater, nsMsgSave, nsMsgSaveAs, nsMsgSaveAsDraft, nsMsgSaveAsTemplate.
nsIMessage *msgToReplace,
- if the delivery mode is set to nsMsgSaveAsDraft, this is a pointer to the the nsIMessage object for the message that needs to be replaced
const char *attachment1_type,
const char *attachment1_body,
PRUint32 attachment1_body_length,
- the full text of the first attachment is provided via `attachment1_type' `attachment1_body' and `attachment1_body_length'. These may all be 0 if all attachments are provided externally.
const struct nsMsgAttachmentData *attachments,
- Subsequent attachments are provided as URLs to load, described in the nsMsgAttachmentData structures.
const struct nsMsgAttachedFile *preloaded_attachments,
- attachments that are already locally stored on disk (note: both attachments and preloaded_attachments cannot be specified on a single call
void *relatedPart /* nsMsgSendPart */,
- a related part for multipart related operations
nsIMsgSendListener **aListenerArray) = 0;
- an array of listeners for the send operation. this can be nsnull if you want to do the delivery operation "blind"

SendMessageFile

The SendMessageFile method will let the caller send a message that has been created by another process (Note: CreateAndSendMessage can accomplish this task).

NS_IMETHOD SendMessageFile(
nsIMsgIdentity *aUserIdentity,
- the user identity for the person doing the send operation. This will be needed to determine the appropriate folder for copy operations.
nsIMsgCompFields *fields,
- the message composition fields. This will contain all of the relevant header information for message delivery
nsFileSpec *sendFileSpec,
- the file spec for the message being sent
PRBool deleteSendFileOnCompletion,
- tell the back end if it should delete the file upon successful completion
PRBool digest_p,
- this is a flag that says that most of the documents we are attaching are themselves messages, and so we should generate a multipart/digest container instead of multipart/mixed. (It's a minor difference.)
nsMsgDeliverMode mode,
- mode is the delivery mode. This can be set for the various modes of delivery. These can include nsMsgDeliverNow, nsMsgQueueForLater, nsMsgSave, nsMsgSaveAs, nsMsgSaveAsDraft, nsMsgSaveAsTemplate.
nsIMessage *msgToReplace,
- if the delivery mode is set to nsMsgSaveAsDraft, this is a pointer to the the nsIMessage object for the message that needs to be replaced
nsIMsgSendListener **aListenerArray) = 0;
- an array of listeners for the send operation. this can be nsnull if you want to do the delivery operation "blind"

SendWebPage

The SendWebPage method is a convenience function that will let the caller send a web page by specifying a URI. NOTE: This can be any valid URI so one can send local disk files by specifying a file:// URI.

NS_IMETHOD SendWebPage(
nsIMsgIdentity *aUserIdentity,
- the user identity for the person doing the send operation. This will be needed to determine the appropriate folder for copy operations.
nsIMsgCompFields *fields,
- the message composition fields. This will contain all of the relevant header information for message delivery
nsIURI *url,
- the URI of the message composition fields. This will contain all of the relevant header information for message delivery
nsMsgDeliverMode mode,
- mode is the delivery mode. This can be set for the various modes of delivery (i.e. send later, drafts, templates or send the message now)
nsIMsgSendListener **aListenerArray) = 0;
- an array of listeners for the send operation. this can be nsnull if you want to do the delivery operation "blind"

The AddListener/RemoveListener methods let the caller add and remove listeners to the sending interface.

NS_IMETHOD AddListener(nsIMsgSendListener *aListener) = 0;
NS_IMETHOD RemoveListener(nsIMsgSendListener *aListener) = 0;

Sending Listener Interfaces

The nsIMsgSendListener interface will let a caller keep track of the progress and any status of a send operation. These are critical for message delivery since message sending is asynchronous. It is the only way to determine if the operation was successful or not. An important item to note is the fact that this interface should also implement the nsIMsgCopyServiceListener interface if it wants to be notified of the progress and completion of the copy operation.

nsIMsgSendListener

The following describes the methods of the nsIMsgSendListener interface:

OnStartSending

The OnStartSending interface is called when the sending operation has begun. This is called after messages creation has completed. If message creation fails, the nsIMsgSend operation will return an NS_FAILED() return code.

NS_IMETHOD OnStartSending(const char *aMsgID,
- the message ID for the message being sent
PRUint32 aMsgSize) = 0;
- the total message size for the message being sent

OnProgress

The OnProgress interface is called with progress notification on the send operation.

NS_IMETHOD OnProgress(const char *aMsgID,
- the message ID for the message being sent
PRUint32 aProgress,
- the progress so far
PRUint32 aProgressMax) = 0;
- the maximum progress (aProgress should be used as a numerator and aProgressMax as a denominator for a message sent percentage)

OnStatus

The OnStatus gives the listener status updates for the current operation.

NS_IMETHOD OnStatus(const char *aMsgID,
- the message ID for the message being sent
const PRUnichar *aMsg) = 0;
- a message concerning the status of the send operation

OnStopSending

The OnStopSending interface is called when the sending operation has completed. This will be called in the case of both success and failure.

NS_IMETHOD OnStopSending(const char *aMsgID,
- the message ID for the message being sent
nsresult aStatus,
- the resulting status for the send operation
const PRUnichar *aMsg,
- a message concerning the status of the send operation
nsIFileSpec *returnFileSpec) = 0;
- an nsIFileSpec which will specify the file that was created (this is used if the dont_deliver_p argument is set to PR_TRUE)

nsIMsgCopyServiceListener

The nsIMsgCopyServiceListener interface will notify the implementor or the progress and completion of the copy operation that follows successful send operations.

OnStartCopy

The OnStartCopy interface is called when the copy operation has begun.

NS_IMETHOD OnStartCopy(
nsISupports *listenerData) = 0;
- the nsISupports pointer passed in to the original copy operation

OnProgress

The OnProgress interface is called with progress notification for the copy operation.

NS_IMETHOD OnProgress(
PRUint32 aProgress,
- the progress so far
PRUint32 aProgressMax) = 0;
- the maximum progress (aProgress should be used as a numerator and aProgressMax as a denominator for a message sent percentage)
nsISupports *listenerData) = 0;
- the nsISupports pointer passed in to the original copy operation

OnStopCopy

The OnStopCopy interface is called when the copy operation has completed. This will be called in the case of both success and failure.

NS_IMETHOD OnStopCopy(
nsresult aStatus,
- the resulting status for the send operation
nsISupports *listenerData) = 0;
- the nsISupports pointer passed in to the original copy operation

Copy Operations

There are various copy operations that can result as a part of message creation and delivery. These are all controlled by the caller in various way. The following details the specific copy operations that can occur in a message send call.

Copy to Sent Folder

Copying to the "Sent" folder is controlled by a setting in the nsIMsgCompFields interface. The SetFcc() and GetFcc() methods are used by the caller to control if a message should be copied to the defined "Sent" folder if the sending operation was successful. Currently, this pref is a "char *" which is the specific name of the folder, but this will more than likely change to a PRBool (boolean) preference. The determiniation of which folder is the "Sent" folder for the user is done by a call to GetFoldersWithFlag() and the message store will control this user defined preference. If the setting for GetFcc() is set to true, the copy operation is automatically performed after a successful send operation.

Drafts

Saving a message as a draft is controlled by the "nsMsgDeliverMode mode" argument of the CreateAndSendMessage and SendMessageFile methods. If the caller passes in nsMsgSaveAsDraft, the file created or passed in will be stored as a draft in the user specified "Drafts" folder.

Templates

Like Drafts, saving a message as a template is controlled by the "nsMsgDeliverMode mode" argument of the CreateAndSendMessage and SendMessageFile methods. If the caller passes in nsMsgSaveAsTemplate, the file created or passed in will be stored as a draft in the user specified "Templates" folder.

Send Later

Developers also have the ability to do "Send Later" operations. This will store messages in the user defined "Unsent Messages or Drafts" folder. This simply does a save operation similar to Drafts and Templates. Send Later operations are controlled by the "nsMsgDeliverMode mode" argument of the CreateAndSendMessage and SendMessageFile methods. If the caller passes in nsMsgQueueForLater.

Sending Unsent Messages

The back end has the ability to send all messages that are currently stored in the user defined "Unsent Messages or Drafts" folder. (See Send Later above) The nsIMsgSendLater is the interface that allows the caller to send all of the files previously stored. The caller will implement an nsIMsgSendLaterListener interface to monitor the progress of the send operations.

The following describes the methods of the nsIMsgSendLater interface. This method is performs the send operations asynchronously.

The SendUnsentMessages method will send all queued messages.

NS_IMETHOD SendUnsentMessages(nsIMsgIdentity *identity,
- the user identity for the person doing the send operation. This will be needed to determine the appropriate folder for copy operations.
nsIMsgSendLaterListener **listenerArray) = 0;
- an array of listeners for the send operation. this can be nsnull if you want to do the delivery operations "blind"

The AddListener & RemoveListener methods will add and remove listeners from the nsIMsgSendLater object.

NS_IMETHOD AddListener(nsIMsgSendLaterListener *aListener) = 0;
NS_IMETHOD RemoveListener(nsIMsgSendLaterListener *aListener) = 0;

Sending Unsent Messages Listener

The nsIMsgSendLaterListener interface will notify the implementor of the progress and completion of the send later operations.

CreateAndSendMessage

The OnStartSending interface is called when the send later operation has begun.

NS_IMETHOD OnStartSending(
PRUint32 aTotalMessageCount) = 0;
- the total messages to be sent

CreateAndSendMessage

The OnProgress interface is called with progress notification of the send later operation.

NS_IMETHOD OnProgress(
PRUint32 aCurrentMessage,
- the current message being sent
PRUint32 aTotalMessage) = 0;
- the total messages to be sent

CreateAndSendMessage

The OnStatus gives the listener status updates for the current operation.

NS_IMETHOD OnStatus(
const PRUnichar *aMsg) = 0;
- the progress so far

CreateAndSendMessage

The OnStopSending interface is called when the send later operation has completed.

NS_IMETHOD OnStopSending(
nsresult aStatus,
- the resulting status for the send operation
const PRUnichar *aMsg,
- a status message
PRUint32 aTotalTried,
- the total messages that were attempted
PRUint32 aSuccessful) = 0;
- the number of successful messages

Quoting

Quoting a mail message is made possible via the nsIMsgQuote interface. It is a simple interface that takes a consumer output stream for the quoted data. The message will be output in HTML form and it is up to the caller to handle plain text conversion.

CreateAndSendMessage

The QuoteMessage method is the primary interface for message quoting.

NS_IMETHOD QuoteMessage(
const PRUnichar *msgURI,
- the URI of the message to be quoted
nsIOutputStream *outStream) = 0;
- the consumer output stream for the quoted data

Sample Programs

The mozilla/mailnews/compose/tests/ directory contains sample test programs for all of the above described interfaces. Use at your own risk and beware of bitrot!

  • compose - this program shows the use of the CreateAndSendMessage interface (CreateAndSendMessage)
  • compose2 - this program shows the use of the CreateAndSendMessage interface (SendMessageFile)
  • sendlater - this program shows the use of the nsIMsgSendLater interface
  • sendpage - this program shows the use of the CreateAndSendMessage interface (SendWebPage)

Last modified: Wed Nov 1, 2000 rhp@netscape.com