Class Message.

Inherits Multipart. Inherited by Injectee.

The Message class is the top-level RFC 822 message parser and generator.

Its core is an email message, and its two duties are conversion to and from RFC 822 format.

I'm writing it towards this: It can parse messages, with the aid of Header and HeaderField, and split them into MIME bodyparts. It can verify the validity of any single message.

This may not be what we really need. In particular, constructing Messages (partially) from Cache needs consideration. We'll see.

This class also provides the utility function baseSubject(), which strips extras such as "Re:" and "(fwd)" off a string to find the presumed base subject of the message.


Constructs an empty Message.

Reimplements Multipart::Multipart().

static EString Message::acceptableBoundary( const EString & parts )

Returns a short string, e.g. "c", which can be used as a mime boundary surrounding parts without causing problems.

parts may be one bodypart, or several separated by CRLF. The important thing is that all the lines which might conflict with the boundary are lines in parts.

void Message::addMessageId()

Adds a message-id header unless this message already has one. The message-id is based on the contents of the message, so if possible, addMessageId() should be called late (or better yet, never).

List<Bodypart> * Message::allBodyparts() const

Returns a list of all Bodypart objects within this Message. The returned pointer is never null, but may point to an empty list.

The Injector relies on children()->first() being first in the list.

static UString Message::baseSubject( const UString & subject )

Tries to remove the prefixes and suffixes used by MUAs from subject to find a base subject that can be used to tie threads together linearly.

EString Message::body() const

Returns the text representation of the body of this message.

Bodypart * Message::bodypart( const EString & s, bool create )

Returns a pointer to the Bodypart whose IMAP part number is s and possibly create it. Creates Bodypart objects if create is true. Returns null pointer if s is not valid and create is false.

uint Message::databaseId() const

Records what setDatabaseId() recorded, or 0 if setDatabaseId() has not been called for this object.

EString Message::error() const

Returns a message describing the first detected syntax error in this message, or an empty string if no error has been detected.

void Message::fix8BitHeaderFields()

Tries to handle unlabelled 8-bit content in header fields, in cooperation with Header::fix8BitFields().

The idea is that if we know which encodings are used for the text bodies, and all bodies agree, then any unlabelled header fields probably use that encoding, too. At least if they're legal according to the relevant codec.

If we can't get charset information from any body, we try to see if a single codec can encode the entire header, and if so, use that.

bool Message::hasAddresses() const

Returns true if this message has read its headers fields from the database, and false it it has not.

bool Message::hasBodies() const

Returns true if this message has read its bodyparts from the database, and false if it has not.

bool Message::hasBytesAndLines() const

Returns true if setBytesAndLinesFetched() has been called, false otherwise.

bool Message::hasHeaders() const

Returns true if this message has read its headers from the database, and false it it has not.

bool Message::hasTrivia() const

Returns true if this message knows its internalDate() and rfc822Size(), and false if not.

uint Message::internalDate() const

Returns the message's internaldate mb, which is meant to be the time when Archiveopteryx first saw it, although it actually is whatever was set using setInternalDate().

If the messages comes from the database, this function's return value is valid only if hasTrivia();

bool Message::isMessage() const

Returns true.

Reimplements Multipart::isMessage().

bool Message::isWrapped() const

Returns what setWrapped() set.

void Message::parse( const EString & rfc2822 )

Wipes out old message content and replaces it with a parse tree based on rfc2822.

static Header * Message::parseHeader( uint & i, uint end, const EString & rfc2822, Header::Mode m )

Creates and returns a Header in mode m by parsing the part of rfc2822 from index i to index end, not including end. i is changed to the index of the first unparsed character.

If there is a leading From-space line, parseHeader() skips it and discards its content. Skipping is fine, but should we discard?

Some messages copied from Courier start with a line like " Feb 12 12:12:12 2012". This code skips that, too.

EString Message::partNumber( Bodypart * bp ) const

Returns the IMAP part number of bp, which must be a part of this Multipart.

void Message::recomputeError()

Asks each Header and Bodypart for error information, and sets a suitable error() message for the entire Message. Clears error() if no Header or Bodypart has an error.

EString Message::rfc822() const

Returns the message formatted in RFC 822 (actually 2822) format. The return value is a canonical expression of the message, not whatever was parsed.

uint Message::rfc822Size() const

Reports the Message's size, as set using setRfc822Size() or the constructor. Valid only if hasTrivia();

void Message::setAddressesFetched()

Notifies this message that it knows what addresses its address fields contain.

void Message::setBodiesFetched()

Records that all the bodies in this Message have been fetched.

void Message::setBytesAndLinesFetched()

Notifies this message that its Bodypart objects know their Bodypart::numEncodedBytes() and Bodypart::numEncodedLines().

void Message::setDatabaseId( uint id )

Records that this message's database ID is id. This corresponds to the id column in the messages row.

void Message::setHeadersFetched()

Records that all the bodies in this Message have been fetched.

void Message::setInternalDate( uint id )

Notifies this Message that its internaldate is id. The Message will remember id and internalDate() will return it.

void Message::setRfc822Size( uint s )

Notifies the Message that its size is s bytes. The Message will believe and report this.

void Message::setTriviaFetched( bool ok )

Records that the message now has correct values for internalDate() and rfc822Size() if ok is true, and that it doesn't if ok is false.

void Message::setWrapped( bool w ) const

Records that this message is a wrapper message if w is true, and that it it's an ordinary message if not. Wrapper message (in this context) are those which wrap an unparsable message.

The initial value is false, of course.

bool Message::valid() const

Returns true if this message is a valid RFC 2822 message, and false if it has known/detected errors. Returns true if the message is known to be incomplete.

This web page based on source code belonging to The Archiveopteryx Developers. All rights reserved.