~matthiasbeyer/maildir

a0a811503c48aaa050c724275807f3bcb6959f20 — Dan Čermák 2 years ago 4eedd81
store_new and store_cur_with_flags now return the id of the inserted mail

Previously there was no trivial way how one could get the id of a freshly
inserted email. This commit modifies the return type of Maildir::store to
Result<String, MaildirError>, and returns the id on success.

The smoke test for store_new was modified to verify that the id is actually the
correct one.
2 files changed, 21 insertions(+), 9 deletions(-)

M src/lib.rs
M tests/smoke.rs
M src/lib.rs => src/lib.rs +10 -8
@@ 384,18 384,20 @@ impl Maildir {
    /// Stores the given message data as a new message file in the Maildir `new` folder. Does not
    /// create the neccessary directories, so if in doubt call `create_dirs` before using
    /// `store_new`.
    pub fn store_new(&self, data: &[u8]) -> std::result::Result<(), MaildirError> {
    /// Returns the Id of the inserted message on success.
    pub fn store_new(&self, data: &[u8]) -> std::result::Result<String, MaildirError> {
        self.store(Subfolder::New, data, "")
    }

    /// Stores the given message data as a new message file in the Maildir `cur` folder, adding the
    /// given `flags` to it. The possible flags are explained e.g. at
    /// <https://cr.yp.to/proto/maildir.html> or <http://www.courier-mta.org/maildir.html>.
    /// Returns the Id of the inserted message on success.
    pub fn store_cur_with_flags(
        &self,
        data: &[u8],
        flags: &str,
    ) -> std::result::Result<(), MaildirError> {
    ) -> std::result::Result<String, MaildirError> {
        self.store(Subfolder::Cur, data, &format!(":2,{}", flags))
    }



@@ 404,7 406,7 @@ impl Maildir {
        subfolder: Subfolder,
        data: &[u8],
        flags: &str,
    ) -> std::result::Result<(), MaildirError> {
    ) -> std::result::Result<String, MaildirError> {
        // try to get some uniquenes, as described at http://cr.yp.to/proto/maildir.html
        // dovecot and courier IMAP use <timestamp>.M<usec>P<pid>.<hostname> for tmp-files and then
        // move to <timestamp>.M<usec>P<pid>V<dev>I<ino>.<hostname>,S=<size_in_bytes> when moving


@@ 449,8 451,8 @@ impl Maildir {
            Subfolder::New => "new",
            Subfolder::Cur => "cur",
        });
        newpath.push(format!(
            "{}.M{}P{}V{}I{}.{},S={}{}",
        let id = format!(
            "{}.M{}P{}V{}I{}.{},S={}",
            ts.as_secs(),
            ts.subsec_nanos(),
            pid,


@@ 458,11 460,11 @@ impl Maildir {
            meta.ino(),
            hostname,
            meta.size(),
            flags
        ));
        );
        newpath.push(format!("{}{}", id, flags));
        std::fs::rename(tmppath, newpath)?;

        Ok(())
        Ok(id)
    }
}


M tests/smoke.rs => tests/smoke.rs +11 -1
@@ 167,8 167,18 @@ fn check_store_new() {
        maildir.create_dirs().unwrap();

        assert_eq!(maildir.count_new(), 0);
        maildir.store_new(TEST_MAIL_BODY).unwrap();
        let id = maildir.store_new(TEST_MAIL_BODY);
        assert!(id.is_ok());
        assert_eq!(maildir.count_new(), 1);

        let id = id.unwrap();
        let msg = maildir.find(&id);
        assert!(msg.is_some());

        assert_eq!(
            msg.unwrap().parsed().unwrap().get_body_raw().unwrap(),
            "Today is Boomtime, the 59th day of Discord in the YOLD 3183".as_bytes()
        );
    });
}