snipsco / postal Goto Github PK
View Code? Open in Web Editor NEWA Swift framework for working with emails
License: MIT License
A Swift framework for working with emails
License: MIT License
I've implemented Gmail Outh2 and pass the access token in. It got this error: error: login("Invalid credentials (Failure)")
Breaks here
❌ /Users/distiller/theios/Pods/Postal/dependencies/module.modulemap:2:12: header 'build/ios/include/libetpan/libetpan.h' not found
header "build/ios/include/libetpan/libetpan.h"
^
❌ /Users/distiller/theios/Pods/Postal/Postal/Address+Parsing.swift:26:8: could not build Objective-C module 'libetpan'
import libetpan
^
Any ideas how to fix, it works locally.
error: SWIFT_VERSION '3.0' is unsupported, supported versions are: 4.0, 4.2, 5.0. (in target 'Result-iOS' from project 'Result')
error: SWIFT_VERSION '3.0' is unsupported, supported versions are: 4.0, 4.2, 5.0. (in target 'Result-iOS' from project 'Result')
Please release new version :(
I would like to set my email provaider diferent then gmail, yahoo, etc. There is a way to this using Postal?
Hi,
I'd like to use ReactiveCocoa 6.0.0 (using ReactiveSwift 2.0.0) in my application, but found out (by a dependency problem with Result 3.1 vs. 3.2), that Postal uses ReactiveSwift 1.
Is there any chance, that Postal works with ReactiveSwift 2 / ReactiveCocoa 6 / Result 3.2.3 ?
Regards,
Eike
Hi klevefre,
you wrote about debugging Postal:
You can set a closure on a Postal instance to have IMAP logs:
let postal = Postal(configuration: ...)
postal.logger { log in
print(log)
}
Unfortunately this doesn't work in my code.
I get the compiler error message "Cannot call value of non-function type 'logger?'
This is my code:
init(hostname: String, userName: String, password: String) {
log.debug("init called...")
configuration = Configuration(hostname: hostname, port: 993, login: userName, password: .plain(password), connectionType: .tls, checkCertificateEnabled: false)
let postal: Postal = Postal(configuration: configuration)
postal.logger { log in
print(log)
}
[...]
What's wrong with my code? It's exactly as you wrote...?
Related: How can I logout?
I'm fetching emails from Gmail, using Postal.
I fetch the last 100 emails, with all flags ([.structure, .size, .flags, .headers, .gmailLabels, .gmailThreadID, .gmailMessageID, .body, .fullHeaders, .headerSubject]
), and then iterate over each fetch result's body.allParts
and fetch the attachments for each part.
When I do this, I don't ever see any text/html parts, only ever text/plain, but when viewing the raw source of the mail on Gmail, it shows there is a text/html and a text/plain.
My code looks like so:
func fetchMail(in folder: Folder) {
mailService?.fetchLast(folder.name, last: 100, flags: allFlags, onMessage: { result in
result.body?.allParts.forEach { part in
print(part.mimeType) // This always prints "text/plain"
self.mailService?.fetchAttachments(folder.name, uid: result.uid, partId: part.id, onAttachment: { mailData in
if let data = Data(base64Encoded: mailData.decodedData, options: .ignoreUnknownCharacters) {
let content = String(data: data, encoding: .utf8)
print(content) // this is always a plain text representation
} else {
let content = String(data: mailData.decodedData, encoding: .utf8)
print(content) // this is always a plain text representation
}
}, onComplete: { error in
if let error = error {
print("Error fetching attachment: \(error)")
}
})
}
}, onComplete: { error in
if let error = error {
print("error fetching email in \(folder.name): \(error)")
return
}
})
}
An example of the log when I'm testing this is as follows:
text/plain
Optional("D4Test was granted access to your Google account\r\n\r\n\r\[email protected]\r\n\r\nIf you did not grant access, you should check this activity and secure your\r\naccount.\r\nCheck activity\r\n<https://accounts.google.com/[email protected]&continue=https://myaccount.google.com/alert/nt/1570456286000?rfn%3D127%26rfnc%3D1%26eid%3D650020303090366957%26et%3D0%26anexp%3Dgivab-fa--mdv2-fa>\r\nYou received this email to let you know about important changes to your\r\nGoogle Account and services.\r\n© 2019 Google LLC, 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA\r\n")
But when I check the source of the email via the Gmail website it shows two parts of the email, one text/plain, which is the plain text encoded as bas64, and the other text/html, but the html part does not appear in the parts in the Postal response.
I'd like to see POP3 support.
我只想获取邮件 的主体内容 如果附件太大会加载很慢的问题. 可以改成手到的吗.
I am trying to move a message from the INBOX into another folder but I get this error:
7 BAD Unrecognized UID subcommand
I am able to fetch the mail with header,body. But after fetching the mail how to parse the data?
Following is my code
postal.fetchLast("INBOX", last: 1, flags: [ .headers,.size,.fullHeaders,.body ], onMessage: { message in
print("new email uid: \(message.uid)")
print("new email body: \(message.body)")
}
How to parse this data received??
I mean basically how can i parse the mail to display in a viewer.
When compiling a project with Postal installed via CocoaPods, the build fails in Extensions+Parsing.swift
with error Use of extraneous '&'
in lines 51, 55, 60 and 64
Upon launching a project that includes Postal as a framework, getting the following warning:
the prompted auto-fix did the following and seems to resolve it:
diff --git a/Postal.xcodeproj/project.pbxproj b/Postal.xcodeproj/project.pbxproj
index c06c1f9..3eed3be 100644
--- a/Postal.xcodeproj/project.pbxproj
+++ b/Postal.xcodeproj/project.pbxproj
@@ -584,10 +584,9 @@
};
buildConfigurationList = 98DB008F1CEC6983003CAABB /* Build configuration list for PBXProject "Postal" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
- English,
en,
Base,
);
(Creating a new issue since I'm not sure what notifications/visibility a comment in a closed issue gets: #84 (comment))
EDIT: Also a tagged release that's stable for XCode 10.2 wouldn't go amiss.
Looks like Gmail requires using OAuth2, otherwise the user has to set their gmail account to be accessible by "less secure" apps. ...
CocoaPods
and Carthage
are awesome tools and make our life really easier, but there are some devs who still don't know how to use them.
It would be cool to add the Manual installation guide in your README.md
. You can take a look at my iOS Readme Template to see how you can do it.
Problem:
We have to optimize the NSIndexSet.enumerate(batchSize: Int)
because of too much complexity in it -> O(n)
Example:
If we try to fetch all emails we would do something like:
let range = NSRange(location: 1, length: Int.max - 1)
let indexSet = NSIndexSet(indexesInRange: range)
var results = [FetchResult]()
try imapSession.fetchMessages("INBOX", set: IMAPIndexes.indexes(indexSet), flags: [ .fullHeaders ]) { _ in }
Current result:
It takes too much time for a provider that have a batchSize == Int.max
to create the only one indexset needed for the fetch.
Expected result:
Instant fetch
Possible solution:
We could try to use the Strideable
protocol instead or simply optimize inside the method.
It was asked here by someone: https://stackoverflow.com/questions/41155748/how-get-mail-content-using-postal-swift-framework
Please let me know if there are any document or dev guide to start? Or how to find out?
Hi -
When installing via Cocoapods, the install succeeds, but when I run a build, I get a bunch of compilation errors. Looks like Cocoapods has version 0.5.0, which appears to be a couple years old, and there are 22 commits to master since that release in GitHub.
When I install using the "manual" method, everything compiles smoothly and I can fetch my inbox using the sample code as expected.
Maybe it's time for a release? :)
Hello,
I am new in this library and I hope I get help here. I use Swift 5.
When I use the following code I get only "ENDED" but nothing else back in the console. No error message. What I am doing wrong?
A happy New Year to all.
Greetings,
Sven
import Foundation
import Postal
let postal : Postal = Postal(configuration: Configuration(hostname: "email.none.none", port: 993, login: "[email protected]", password: .plain("test"), connectionType: .tls, checkCertificateEnabled: true, batchSize: 1000, spamFolderName: "junk"))
func getEmail() {
let indexset = IndexSet(integer: 1)
postal.fetchMessages("INBOX", uids: indexset, flags: [ .headers ], onMessage: { email in
print("new email received: \(email)")
}, onComplete: { error in
if error == error {
print("an error occured: \(error)")
}
})
}
postal.connect { result in
switch result {
case .success:
getEmail()
case .failure(let error):
print("error: \(error)")
}
}
print("ENDED")
I am able to fetch message subject but I cannot fetch what's written in thr body of email. Plz help in swift
I was wondering if Postal supports Push (i.e. the user's email server informing an app that uses Postal about new messages). As far as I understand, this is known under the name IDLE (https://tools.ietf.org/html/rfc2177).
I didn't find any traces of it in the examples or in documentation/roadmap, so I thought I would ask how big the interest is in implementing it or if there have been any plans already.
I have also checked libetpan
and it seems like it's available there. If implementing it is (in your opinion) uncomplicated enough for me to try it without substantial C experience, I'd love a tip on where to start.
Otherwise, I would greatly appreciate any advice on what other packages I might use for that functionality in a macOS app. I'm writing it in Swift, but wouldn't mind using a package from another language, if the interop works. From what I found, MailCore or libetpan could be my only options, would be interested to find out otherwise.
Thanks for any advice/help and to the contributors for their work.
As mentioned in the recent XCode 10.2 PR thread: #83 (comment)
Result module was removed but is still referenced in Postal.podspec. I don't use pods in my project so I'm not sure what issues this may cause.
Postal-iOS framework has 7 swift language-related warnings:
Is it possible to sign in to an icloud account that has two-factor auth enabled?
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])
I try to access my IMAP server with this code, which is based on your demo code:
`
import Foundation
import Postal
class MailManagerPostal {
var configuration: Configuration!
fileprivate lazy var postal: Postal = Postal(configuration: self.configuration)
fileprivate var messages: [FetchResult] = []
init(hostname: String, userName: String, password: String) {
log.debug("init called...")
configuration = Configuration(hostname: hostname, port: 993, login: userName, password: .plain(password), connectionType: .tls, checkCertificateEnabled: false)
log.debug("configuration created: \(self.configuration.description)")
postal.connect(timeout: Postal.defaultTimeout, completion: { [weak self] result in
log.debug("postal.connect completed.")
switch result {
case .success:
log.debug("fetching messages now.")
let indexset = IndexSet(0...100000)
self?.postal.fetchMessages("INBOX", uids: indexset, flags: [ .fullHeaders ], onMessage: { message in
log.debug("message : \(message.header)")
self?.messages.insert(message, at: 0)
}, onComplete: { error in
if let error = error {
log.error("fetch failed: \((error as NSError).localizedDescription)")
} else {
log.debug("connection successful")
}
log.debug("fetch complete.")
})
case .failure(let error):
log.error("connection failed: \((error as NSError).localizedDescription)")
}
})
log.debug("init finished.")
}
}
`
Problem: The last message I see is "fetching messages now.". Then nothing happens any more. What's happening here? Where is my mistake? The credentials I use work with using mailcode2 without a problem.
Some more questions:
hi i'm using this code to retrive some messages from my account
postal.connect(timeout: Postal.defaultTimeout, completion: { [weak self] result in
switch result {
case .success:
let filter = .unread && .from(value: "[email protected]")
self?.postal.search("INBOX", filter: filter) { result in
switch result {
case .success(let indexes):
self?.postal.fetchMessages("INBOX", uids: indexes, flags: [ .fullHeaders ], onMessage: { message in
self?.messages.insert(message, at: 0)
}, onComplete: { error in
if let error = error {
self?.showAlertError("Error Obteniendo los Mensajes", message: (error as NSError).localizedDescription)
} else {
self?.tableView.reloadData()
}
})
case .failure(let error):
self?.showAlertError("Error Obteniendo los Mensajes Filtrados", message: (error as NSError).localizedDescription)
}
}
case .failure(let error):
self?.showAlertError("Error de Connección", message: (error as NSError).localizedDescription)
}
})
}
my questions are, i'm doing something wrong? there is an easy way? what is xpc connection interrupted?, i cant find nothing in google.
I guess, it only matters to have connection to the network by data mobile or wifi, but I wonder, if I am using mobile data for my connection to the network, this influences something..
Swift4.0 fetchMessage method flags value
[.fullHeaders,.flags,.headerSubject,.internalDate,.headers,.structure,.uid]
Can't get flags value
Is there a way to check if an email body contains text/html and fallback to fetching plain/text?
If a user want to create a class/struct/enum that as the same name as a public data type in Postal. The compiler will conflict with Postal class name and the Postal module.
e.g.
// Target1:
struct Address {
}
let postalAddress: Postal.Address = ... // Don't compile - try to find a nested type of the class Postal
let targetAddress: Address = ... // Compile but Target.Address
It is a known bug and I thought swift3 would fix this issue but it didn't and it becomes really annoying to whoever want to have a class named Address
, or MessageHeader
(every public class in Postal) for a complete other purpose...
To fix this I would propose to rename the Postal
class for PostalClient
. @jeremiegirault WDYT ?
ConnectionLogType.dataReceived: 1 NO [AUTHENTICATIONFAILED] Authentication failed
login(description: "Authentication failed")
I have create app specific password also but same its coming
I am reading my emails like this:
func fetch ( forNumber: Int )
{
pConnector?.fetchLast ( "INBOX", last: UInt(forNumber), flags: [ .headers ], onMessage:
{ email in
print("Got Message: \(email)");
}, onComplete:
{ error in
if let error = error
{
print("Error! \(error) ")
}
} )
}
However, I get this as a response:
FetchResult(uid: 15430, header: nil, flags: MessageFlag., body: nil, rfc822Size: 0, internalDate: nil, gmailThreadId: nil, gmailMessageId: nil, gmailLabels: nil)
I am new to swift, and am just learning about how this library works so I am probably doing something wrong; Just not quite sure what. I would love to know why this is happening - Thanks
As you can see, after enabling the logger it does spit out some data. This leads me to believe that there is something wrong with the api/lib.
* 569 FETCH (UID 15430 ENVELOPE ("Mon, 22 Jan 2018 16:33:45 +0000 (GMT)" "The status for your app, Quick Things (1330243459), is now Ready for Sale." (("iTunes Store" NIL "no_reply" "email.apple.com")) (("iTunes Store" NIL "no_reply" "email.apple.com")) (("iTunes Store" NIL "no_reply" "email.apple.com")) ((NIL NIL "z.zoelec2" "gmail.com")) NIL NIL NIL "<[email protected]>") BODY[HEADER.FIELDS (References)] {2}
It appears that giving an IndexSet to fetchMessages() with a single index actually tries to fetch 2 messages. This also means that fetchLast() fails.
i.e.
let indexset = IndexSet(integer: 2750)
postal.fetchMessages("INBOX", uids: indexset, flags: [ .fullHeaders ], ...
actually tries to fetch messages 2750 and 2751.
Are you working on a Swift 3.0 compatible version?
See here, https://github.com/snipsco/Postal/blob/master/dependencies/build-dependencies.sh#L92
We should switch to xcodebuild
I have simple iOS app which connect to my gmail and get last 10 emails:
private lazy var oauthswift:OAuth2Swift = {
let tempOauthswift = OAuth2Swift(
consumerKey: "MY_SECRET_KEY",
consumerSecret: "",
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",//!!!!!!!!!!!!!!!!!
responseType: "code"
)
tempOauthswift.allowMissingStateCheck = true
return tempOauthswift
}()
@IBAction func tap(_ sender: Any) {
oauthswift.authorize(
withCallbackURL: URL(string: "MY_CALLBACK_URL:/oauth2Callback")!,
scope: "https://mail.google.com/", state:"",
success:
{
(credential, response, parameters) in
let configuration = Configuration.gmail(login: "[email protected]", password: .accessToken(credential.oauthToken))
print(credential.oauthToken)
let postal = Postal(configuration: configuration)
postal.connect { result in
switch result {
case .success:
print("success")
case .failure(let error):
print("error: \(error)")
}
}
postal.fetchLast("INBOX", last: 10, flags: [.body], onMessage: { (FetchResult) in
print(FetchResult)
}, onComplete: { (PostalError) in
print(PostalError
.debugDescription)
})
},
failure:
{ error in
print("Error: \(error.localizedDescription)")
})
}
My app fetches emails successfully but Instruments shows leaks:
Any ideas?
when I try to log in it is showing
error: login(description: "Authentication Failed")
currently trying to login with iCloud
It would contains user authentication UI similarly to the Mail app.
Whenever I try to connect to any e-mail account, I am getting a certificate error.
error: certificate. The operation couldn’t be completed. (Postal.PostalError error 4.)
Can I use postal in a Objective-C project?
Today we dispatch results on the main thread because we assume that Postal is mostly used for UI purpose which is not necessarily true.
It's just an idea but I think we should remove this behaviour because if we use Postal for processing purpose we may not want Postal to enqueue on the main queue (even if here we are talking about very lightweight messages). Users might want to save some computations from the main-thread before actually displaying something to the UI.
So I would propose to drop this behaviour. As an example NSURLSession
doesn't dispatch on the main thread even if the most common usage of it is to display something fetched from internet on the UI. And if we think about it. Postal and NSURLSession do, in a sense, the same kind of work...
As an alternative, we could add an option to the Postal instance or adding a parameter to methods that have a completion handler to let the choice to dispatch results on the main thread or not.
Hi! I’m trying to fetch the email bodies. I have connected and got the headers correct but when I try to fetch the body it says “body: nil” also RFC size is 0.
How can I fetch it correctly? Is it my problem or is it from the API?
Thanks.
I have created a mail app using Postal Framework and my mail server send the message to app with different type data, so how I know a data in body is encode/decode by type?
In my example I don't know data should encode with NSUTF8StringEncoding
or NSISO2022JPStringEncoding
:(
msg.body?.allParts.forEach({ (singlePart) in
let meesage = String.init(data: (singlePart.data?.rawData)!, encoding: NSUnicodeStringEncoding)
if singlePart.mimeType == MimeType.textPlain {
mailInfo.messageDescription = meesage?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) ?? ""
} else if singlePart.mimeType == MimeType.textHtml {
mailInfo.message = meesage ?? ""
}
})
Thanks for support!
My project crash with this error code
👎 linker command failed with exit code 1 (use -v to see invocation)
its brand new project with only Postal implemented and 1 function to ''connect''.
Could anybody please help
import UIKit
import Postal
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
postaloTest()
}
let login = "[email protected]"
let password = "password123"
func postaloTest (){
let postal = Postal(configuration: .icloud(login: login, password: password))
postal.connect { result in
switch result {
case .success:
print("success")
case .failure(let error):
print("error: \(error)")
}
}
}
}
Why do we skip sending mail functionality?
I do not want to use old Objective C MailCore.
Could not find any alternative for iOS
I'm struggling to find the right API to use to retrieve the message body. If I take the raw data from a message part, I can convert it to a String but it has extraneous characters. Is there an API to use to get the contents of a message?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.