collect_emails() creates a network of who writes to whom from the
headers of a mailbox that has been exported to file.
It reads the From, To, Cc, Bcc, Date, and Message-ID fields of
each message, and creates a network in which the nodes are email addresses
and each tie runs from the sender of a message to one of its recipients.
Only the headers are read: neither the subject nor the body of any message
is collected.
collect_emails(file = file.choose(), ego = NULL, twomode = FALSE)Inspired by Nathan Yau's "Downloading Your Email Metadata", https://flowingdata.com/2014/05/07/downloading-your-email-metadata/
A character string with the path to an 'mbox' file, an '.eml' file, or a directory holding any number of either, including 'Maildir' folders. If left unspecified, an OS-specific file picker is opened to help users select a file. Note that a file picker cannot select a directory, so the path to a directory must be given.
A character vector of the email address(es) of the owner of the mailbox. By default NULL, in which case ego is inferred from the messages. Use FALSE where the messages are not from one mailbox.
Logical. If TRUE, a two-mode network of addresses and the messages they sent or received is returned, in which the ties are layered by the role each address had in each message. By default FALSE, which returns a directed one-mode network of addresses.
A stocnet object.
Nodes hold the address as their label, the name most often displayed
alongside it, and whether the address is ego's.
Most email clients and services can export a mailbox to file.
Google Takeout, Thunderbird (via "ImportExportTools NG"),
and Apple Mail ("Mailbox > Export Mailbox...") write the 'mbox' format,
in which the messages follow one another in a single file.
Outlook and others can save messages as individual '.eml' files instead.
collect_emails() reads either, as well as 'Maildir' folders,
and needs neither a password nor a connection to the mail server.
Emails are events, and so the network returned is dynamic.
By default each tie is stamped with the time its message was sent,
and several messages between the same two addresses are several ties.
Use to_time() or to_aggregated() to scope or aggregate them.
Where twomode = TRUE the time belongs to the message rather than to
any one of its ties, and so each message instead enters the network at
the time it was sent.
An address is counted once for each message, as its sender if it sent it,
and otherwise under the first of To, Cc, and Bcc that names it.
Messages repeated in the export, as where a message carries several
labels, are collected once, and messages without both a sender and at
least one other recipient are dropped.
A mailbox holds the messages that its owner sent or received,
and so its boundary is that of an ego network:
two alters are only tied where ego was party to the message.
It is not an egocentric network in the sense of is_egocentric(), though,
since the ties are records of events rather than ego's reports of them.
Not every export is one person's mailbox.
By default, the address party to the most messages is taken to be ego
where it is party to at least half of them, and the network is otherwise
taken to have no ego, as in a corpus of several mailboxes.
Note that the address of a mailing list will be found this way too.
Name ego's address(es) in ego to override this, or use ego = FALSE.
mbox <- tempfile(fileext = ".mbox")
writeLines(c("From - Mon Jan 6 09:15:00 2025",
"Message-ID: <1@example.org>",
"Date: Mon, 6 Jan 2025 09:15:00 +0100",
"From: Ada <ada@example.org>",
"To: Ben <ben@example.org>, cy@example.org",
"",
"Shall we meet?",
"",
"From - Mon Jan 6 10:02:00 2025",
"Message-ID: <2@example.org>",
"Date: Mon, 6 Jan 2025 10:02:00 +0100",
"From: Ben <ben@example.org>",
"To: Ada <ada@example.org>",
"Cc: cy@example.org",
"",
"Yes, let's."), mbox)
collect_emails(mbox)
collect_emails(mbox, twomode = TRUE)