Open ikemuc opened 7 years ago
I don't think you can modify an IMAP message like that but we can definitively try to implement a "flag setters". MailCore does something like that: https://github.com/MailCore/mailcore2/blob/2a07d182fff49f453f845298101bea7531da40f2/src/core/imap/MCIMAPSession.cpp#L1726 . Could it be what you need ?
Only setting flags will not help me, but it would be definitely a good first step.
For my app I need to set custom headers also like a "X-MyCustomHeader: 2017-02-25"
The code I'm using in my mailcore2 implementation looks like this. It's a bit more complicated than necessary, because the mailcore2 MessageBuilder doesn't have an init(data: msgData) method (which takes an existing message and clones it so that I can modify the message and APPEND it back on the server). So currently I'm reading the message, copying it manually to a new one in the MessageBuilder, add my custom headers and then APPEND it (adding/modifying also custom flags).
The only thing, which currently doesn't work in mailcore2 for me is, that when I copy the parts, the text message is uuencoded, so it's not human readable any more. When I use other methods to set the text (not as an attachment), the whitespaces are removed.
So yes, it's not possible to modify headers of an existing message on the IMAP server, but it's possible to create a new message and modify the custom headers and flags there and append it back on the server.
Maybe this helps you understanding, what I want to do?
Here's my current code using mailcore2:
//
// setCustomHeader()
//
func setCustomHeader(withFolder: String, uid: UInt32) -> Void {
// 1. read complete message
let fetchOp = imapSession.fetchMessageOperation(withFolder: withFolder, uid: uid)
// start the IMAP operation, which is defined in fetchOp
fetchOp?.start { (err, msgData) -> Void in
log.debug("error from server \(err)")
// 2. add a custom header to the message
let messageParser: MCOMessageParser = MCOMessageParser(data: msgData)
let messageBuilder: MCOMessageBuilder = MCOMessageBuilder()
// copy headers
messageBuilder.header = messageParser.header
messageParser.header.setExtraHeaderValue("Test", forName: "X-MyCustomHeader")
let abstractMainPart: MCOAbstractPart = messageParser.mainPart()
if abstractMainPart.partType == MCOPartType.single {
messageBuilder.header.removeExtraHeader(forName: "Content-Type")
let attachment: MCOAttachment = abstractMainPart as! MCOAttachment
messageBuilder.addAttachment(attachment)
}
else if abstractMainPart.partType == MCOPartType.multipartMixed {
// remove header "Content-Type: multipart/mixed;boundary="------------XXXXXX", otherwise attachments are not shown...
messageBuilder.header.removeExtraHeader(forName: "Content-Type")
let multipartMixedPart: MCOMultipart = abstractMainPart as! MCOMultipart
log.debug("multipartMixedPart: \(multipartMixedPart)\n")
for part in multipartMixedPart.parts {
log.debug("part: \(part)")
let attachment: MCOAttachment = part as! MCOAttachment
log.debug("attachment.mimeType: \(attachment.mimeType)")
log.debug("attachment.decodedString(): \(attachment.decodedString())")
messageBuilder.addAttachment(attachment)
}
}
// 3. write copy of complete message
let appendOp = self.imapSession.appendMessageOperation(withFolder: withFolder, messageData: messageBuilder.data(), flags: MCOMessageFlag(rawValue: 0), customFlags: ["$label1"])
appendOp?.start{ (err, createdUid) in
log.debug("error from server \(err)")
log.debug("created uid: \(createdUid)")
}
}
Hi Kevin,
as my project makes steps forward I now would need to have a method to APPEND a new message. Are there plans to develop more IMAP functionality in Postal? (as the last activity is some months ago...) Currently I'm building my software on top of Postal...
The other option is that I learn how Postal is built and start developing more functionality. But as I'm not a Swift expert, I think some help from you to get into the code would be fine ;-)
Hi @ikemuc , first of all, I apologize for not having answering you before.
Unfortunately, we don't have any plan to add new functionalities to Postal since here at Snips, we are focus on our embedded speech recognition platform (go on https://snips.ai/ and https://console.snips.ai/ for more info ).
We'll add support for Swift 4, and eventually fix bugs users would submit but that's it.
If you want to add new functionalities, I will review your PRs with pleasure.
To understand how Postal was built, you have to know that Postal is based on, libetpan, a C library that manage IMAP for us. Postal is "only" a wrapper of this library, exactly like MailCore by the way.
Postal has exactly the same features as MailCore, we only kept what we thought was the most useful for us at the time we wrote it. Keeping it stupid simple was the primary goal. Also the simplicity of the code since Postal is build in Swift whereas MailCore is a mix of C, C++ and Objective-C.
Look this implementation in Postal: https://github.com/snipsco/Postal/blob/master/Postal/IMAPSession%2BFolder.swift#L39
And now this one in MailCore: https://github.com/MailCore/mailcore2/blob/65bc5a2c045c38b35709964be614f5ceabc637ed/src/core/imap/MCIMAPSession.cpp#L1587
It's exactly the same thing but one is in swift and the other in C++.
If you wan to ingrate your feature, you should convert this method from MailCore: https://github.com/MailCore/mailcore2/blob/65bc5a2c045c38b35709964be614f5ceabc637ed/src/core/imap/MCIMAPSession.cpp#L1731 in Swift.
OK, thank you for your update! I'll try to add the functionality that I need :-)
Hi Kevin,
You wrote "If you want new features, please submit an issue and we'll figure out how to implement them as quickly as possible 👍" so here is what I need to do in my application next. Maybe you can help me by implementing it. Meanwhile I'll try to understand how your code works so maybe I can contribute also by expanding the Postal API to cover more/all of the libetpan API. :-)
Here is what I want to do:
"As a developer of a mail app I want to add custom headers to an IMAP message on the server and manipulate flags of an IMAP message in order to add additional information to an IMAP message."
As IMAP servers typically don't support changing an existing message, you have to:
It would be fantastic, if you could help me as I'm stuck (tried this with mailcore2 already, but it didn't work and ) :-) (the current unsolved problem of my workaround for the problem, that there is no init() method for cloning an existing message into a new message in the MessageBuilder is [https://github.com/MailCore/mailcore2/issues/1607])