enough-software / enough_mail Goto Github PK
View Code? Open in Web Editor NEWIMAP, POP3 and SMTP clients for Dart developers. Contains both low level as well as a high level API.
License: Mozilla Public License 2.0
IMAP, POP3 and SMTP clients for Dart developers. Contains both low level as well as a high level API.
License: Mozilla Public License 2.0
Compare https://tools.ietf.org/html/rfc3501#section-6.3.11
The APPEND command is used for adding messages on the IMAP server.
The UID command has two forms.
In the first form, it takes as its arguments a COPY, FETCH, or STORE command with arguments appropriate for the associated command. However, the numbers in the sequence set argument are unique identifiers instead of message sequence numbers.
In the second form, the UID command takes a SEARCH command with SEARCH command arguments. The interpretation of the arguments is the same as with SEARCH; however, the numbers returned in a SEARCH response for a UID SEARCH command are unique identifiers instead of message sequence numbers.
Polling for new messages is a common client activity, e.g. after longer disconnects or in cases when IDLE
cannot be used due to backgrounding limitations of the OS.
A high level API for quickly checking for new messages should be possible by combining and sending several commands such as LOGIN
and SELECT
at once. Also use future support for QResync ( compare #41).
Provide option to parse MIME messages, e.g. the response of an IMAP FETCH BODY[]
command.
The COPY command copies the specified message(s) to the end of the specified destination mailbox.
Compare https://tools.ietf.org/html/rfc3501#section-6.4.7
Currently only LOGIN command is supported.
Compare https://tools.ietf.org/html/rfc3501#section-6.2.2
hello, first of all thanks for creating this plugin. To my knowledge this is the first plugin that combine SMTP and IMAP in one plugin. I'm somewhat new in programming world and i'm working on a project that need this plugin. can you please provide simple example how can i use the SMTP client to connect->login-> sendMSG. thank you so much.
Support the IMAP METADATA extension, https://tools.ietf.org/html/rfc5464
It works well when pass the folder name INBOX, but when pass the other folder names like SENT, OUTBOX, method returns the result null.
var listResponse=await client.selectMailboxByPath("SENT");
How can use listener when arrived new mails?. I see in log when arrived mails but haven't callback. Help me to implementation idle Start correctly.
Hello.
I couldnt manage handling fetched data.
I need to convert data to UTF-8 Charset, as soon as not everybody uses English Characters.
If there is a pattern which I couldn't find, please tell.
Currently BODY[MIME] part specifiers are ignored in FETCH responses.
Removes all as deleted marked messages from the selected mailbox.
Compare https://tools.ietf.org/html/rfc3501#section-6.4.3
Support responses to FETCH commands that use
Currently SMTP API users need to parse responses to ehlo()
manually. There should be a high level API for accessing such data, e.g. to retrieve the maximum size of messages, if 8 bit / utf-8 messages are accepted, etc.
Sample response:
250-PIPELINING
250-SIZE 200000000
250-ETRN
250-AUTH PLAIN LOGIN OAUTHBEARER
250-AUTH=PLAIN LOGIN OAUTHBEARER
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
Also compare https://cr.yp.to/smtp/ehlo.html
Current BODY[HEADER.FIELDS.NOT] part identifiers are ignored in a FETCH response.
Many IMAP commands use message sequences such as '1:*', '1,4,5:10', etc.
ImapClient should allow to use a simple abstraction for easily creating such sequences.
BODYSTRUCTURE is almost the same as the already supported BODY fetch response:
A parenthesized list that describes the [MIME-IMB] body
structure of a message. This is computed by the server by
parsing the [MIME-IMB] header fields, defaulting various fields
as necessary.
When I send the mail with the attachment from enough_mail smtp client. Email send successfully to the recipient but when try to fetch the file name with the above code, attribute was called on null. But, when I send mail from Outlook or other client, the above code works fine.
Code
mimeMessage.body.structures.first.attributes.first.value
Email Send Code
var builder = MessageBuilder.prepareMultipartMixedMessage();
builder.from = [MailAddress('Sender', '[email protected]')];
builder.to = [MailAddress('Receiver', '[email protected]')];
builder.subject = "Test Email Attachments";
builder.addPlainText("Test Email Attachments");
attachments.forEach((f) {
await builder.addFile(f.file, MediaType.fromText('application/pdf'));
});
var mimeMessage = builder.buildMimeMessage();
var sendResponse = await client.sendMessage(mimeMessage);
print('message sent: ${sendResponse.isFailedStatus}');
To allow quick synchronization, support QRESYNC and CONDSTORE extension.
Compare https://tools.ietf.org/html/rfc7162 for details.
Facing an issue that, if not using app for 30 or maybe 60 minutes or app is in background for that specific time, After that, If I opened the app and by using the previous IMAP login and socket connection, call any IMAP function like fetchMessagesByCriteria() or other, they didn't response back or they give the SocketException. Currently, I am trying to resolve this issue with the ImapClient.isLoggedIn, but it didn't help to resolve this issue. Please guide how I resolve this issue.
Log
I/flutter (27861): C: a14 LIST "" *
I/flutter (27861): 56.0
I/flutter (27861): 56.0
I/flutter (27861): Error: SocketException: OS Error: Connection reset by peer, errno = 104, address = serverAddress, port = 53324
I/flutter (27861): Done, connection closed
E/flutter (27861):
Note
Already handled the Socket Exception, but trying to find out the workaround to check the socket connection and session and then call the IMAP functions.
A server advertising the ESEARCH capability supports the following result options: minimal value, maximal value, all found messages, and number of found messages. These result options allow clients to get SEARCH results in more convenient forms, while also saving bandwidth required to transport the results, for example, by finding the first unseen message or returning the number of unseen or deleted messages. Also, when a single MIN or a single MAX result option is specified, servers can optimize execution of SEARCHes.
Compare https://tools.ietf.org/html/rfc4731 for details.
contentDisposition always null, even if there is an attachments in the email.
Code
var fetchResponse = await S.sImapClient.fetchMessagesByCriteria('$sequenceID (BODYSTRUCTURE BODY.PEEK[])');
print(fetchResponse.result.first.body.structures.first.contentDisposition);
Compare already existing STARTTLS implementation of the SmtpClient.
Also see https://tools.ietf.org/html/rfc3501#section-6.2.1
i have this error after update to v0.0.17
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'toLowerCase' was called on null.
Receiver: null
Tried calling: toLowerCase()
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 ContentTypeHeader.setParameter (package:enough_mail/mime_message.dart:804:17)
#2 FetchParser._parseBody (package:enough_mail/src/imap/fetch_parser.dart:353:16)
#3 FetchParser._parseBodyStructure (package:enough_mail/src/imap/fetch_parser.dart:361:5)
#4 FetchParser._parseFetch (package:enough_mail/src/imap/fetch_parser.dart:77:11)
#5 FetchParser.parseUntagged (package:enough_mail/src/imap/fetch_parser.dart:32:11)
#6 CommandTask.parseUntaggedResponse (package:enough_mail/src/imap/command.dart:73:21)
#7 ImapClient.onUntaggedResponse (package:enough_mail/imap/imap_client.dart:1051:31)
#8 ImapClient.onServerResponse (package:enough_mail/imap/imap_client.dart:1019:7)
#9 ImapResponseReader._checkResponse (package:enough_mail/src/ima<…>
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'toLowerCase' was called on null.
Receiver: null
Tried calling: toLowerCase()
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 ContentTypeHeader.setParameter (package:enough_mail/mime_message.dart:804:17)
#2 FetchParser._parseBody (package:enough_mail/src/imap/fetch_parser.dart:323:35)
#3 FetchParser._parseBodyStructure (package:enough_mail/src/imap/fetch_parser.dart:361:5)
#4 FetchParser._parseFetch (package:enough_mail/src/imap/fetch_parser.dart:77:11)
#5 FetchParser.parseUntagged (package:enough_mail/src/imap/fetch_parser.dart:32:11)
#6 CommandTask.parseUntaggedResponse (package:enough_mail/src/imap/command.dart:73:21)
#7 ImapClient.onUntaggedResponse (package:enough_mail/imap/imap_client.dart:1051:31)
#8 ImapClient.onServerResponse (package:enough_mail/imap/imap_client.dart:1019:7)
#9 ImapResponseReader._checkResponse (package:enough_mail/src/ima<…>
Need some documentation to understand how these two listeners work. I just add the ImapMessagesRecentEvent listener to listen for the new email, and send the email to the client(user). But the listener not listen the new email message.
Code
S.sImapClient.eventBus.on<ImapMessagesRecentEvent>().listen((event) {
print("event.eventType ${event.eventType} ${event.newMessagesRecent} ${event.oldMessagesRecent}");
});
Need some documentation to fetch the attachment detail from the Mime Message and how we find part id/no for attachments to pass in the BODY[part id/no]. Actually, I manage to fetch the attachment by fetching the specific body part from Body, which was working fine before the 0.0.18 version.
Code
var fetchResponse = await S.sImapClient.fetchMessagesByCriteria('$sequenceID (BODY[$part])');
Provide a convenience method for forwarding an existing mime message easily.
Updates the flag(s) of the specified message(s).
Compare https://tools.ietf.org/html/rfc3501#section-6.4.6
The API is inconsistent, for example MimePart.decodePlainTextPart()
or MimePart.decodeHtmlTextPart()
should be called decodeTextPlain()
and decodeTextHtml()
to be aligned with the MIME media type names.
Lookout for other odd spots before increasing version to 0.1.0.
Compare https://tools.ietf.org/html/rfc3501#section-6.4.1, similar to already supported NOOP
Most IMAP extensions are used by the client when it wants to and the server supports it. However, a few extensions require the server to know whether a client supports that extension. The ENABLE extension allows an IMAP client to say which extensions it supports.
Compare https://tools.ietf.org/html/rfc5161 for details
IDLE
support is quite complex, compare #31 .
enough_mail should have an high level API that helps listening for messages.
Such an API could contain:
IDLE
whenever a different command is triggeredNOOP
polling when IDLE
is not supportedSupport the UIDPLUS extension:
Note that the status codes APPENDUID and COPYUID are already exposed by the GenericImapResult.responseCodeAppendUid
and GenericImapResult.responseCodeCopyUid
getters.
Currently the response to FETCHing a BODY[HEADER.FIELDS(DATE FROM)] cannot be read.
Some headers are encoded with ISO-8859-1, for example
'''
From: Tester =?iso-8859-1?Q?Bj=F6rn?= [email protected]
'''
Allow to decode such headers.
Support the commands MOVE and UID MOVE.
Consider falling back to COPY / UID COPY and STORE \Deleted flag on original message for servers that do not have the MOVE capability.
I want to attach the doc types like pdf, xlsx , docx and others. But when I add these type of files, email send successfully with the attachments. But their file formats change to txt. Please guide about the MediaSubtype for the documents like pdf, xlsx , docx. Also, it's not using the real file name.
Code
var builder = MessageBuilder.prepareMultipartMixedMessage();
builder.from = [MailAddress('Sender', '[email protected]')];
builder.to = [MailAddress('Receiver', '[email protected]')];
builder.subject = "Test Email Attachments";
builder.addPlainText("Test Email Attachments");
attachments.forEach((f) {
builder.addFile(f.file, MediaType.fromSubtype(MediaSubtype.multipartMixed));
});
var mimeMessage = builder.buildMimeMessage();
var sendResponse = await client.sendMessage(mimeMessage);
print('message sent: ${sendResponse.isFailedStatus}');
Support the IMAP store command
Currently there are different low level authentication methods supported:
ImapClient.login(String name, String password)
ImapClient.authenticateWithOAuth2(String user, String accessToken)
ImapClient.authenticateWithOAuthBearer(String user, String accessToken, {String host, int port})
There should be one common high level API to authenticate with these various methods. This would also be useful for enabling future automatic reconnect functionality.
Hey,
it possibly a stupid error, but I can't figure out why I can't connect to the gmail smtp server using the following lines:
var client = SmtpClient('gmail.com', isLogEnabled: false);
await client.connectToServer('smtp.gmail.com', 465, isSecure: true);
It fails with the following error:
Unhandled Exception: SocketException: OS Error: Connection timed out, errno = 110, address = smtp.gmail.com, port = 44852
Thanks for feedback
Currently it is not possible to parse a response with several literals at once, e.g.
* 1 FETCH (BODY[TEXT] {6}<CRLF>
Hi<CRLF>
<CRLF>
BODY[HEADER.FIELDS(DATE)] {47}<CRLF>
Date: Tue, 21 Jan 2020 11:59:55 +0100 (CET)<CRLF>
<CRLF>
)<CRLF>
A010 FETCH completed<CRLF>
Null Exception occurred when trying to fetch email with sequence Id.
Code
var fetchResponse = await S.sImapClient.fetchMessagesByCriteria('$sequenceID (BODY BODY.PEEK[])');
Log
E/flutter (23042): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Invalid argument(s): The source must not be null
E/flutter (23042): #0 int.tryParse (dart:core-patch/integers_patch.dart:107:25)
E/flutter (23042): #1 FetchParser._parseBody (package:enough_mail/src/imap/fetch_parser.dart:240:24)
E/flutter (23042): #2 FetchParser._parseFetch (package:enough_mail/src/imap/fetch_parser.dart:74:11)
E/flutter (23042): #3 FetchParser.parseUntagged (package:enough_mail/src/imap/fetch_parser.dart:32:11)
E/flutter (23042): #4 CommandTask.parseUntaggedResponse (package:enough_mail/src/imap/command.dart:73:21)
E/flutter (23042): #5 ImapClient.onUntaggedResponse (package:enough_mail/imap/imap_client.dart:966:31)
E/flutter (23042): #6 ImapClient.onServerResponse (package:enough_mail/imap/imap_client.dart:934:7)
E/flutter (23042): #7 ImapResponseReader._checkResponse (package:enough_mail/src/imap/imap_response_reader.dart:72:28)
E/flutter (23042): #8 ImapResponseReader._checkResponse (package:enough_mail/src/imap/imap_response_reader.dart:53:9)
E/flutter (23042): #9 ImapResponseReader.onData (package:enough_mail/src/imap/imap_response_reader.dart:22:7)
E/flutter (23042): #10 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter (23042): #11 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (23042): #12 _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
E/flutter (23042): #13 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (23042): #14 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:266:7)
E/flutter (23042): #15 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:779:19)
E/flutter (23042): #16 _StreamController._add (dart:async/stream_controller.dart:655:7)
E/flutter (23042): #17 _StreamController.add (dart:async/stream_controller.dart:597:5)
E/flutter (23042): #18 _Socket._onData (dart:io-patch/socket_patch.dart:1982:41)
E/flutter (23042): #19 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter (23042): #20 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (23042): #21 _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
E/flutter (23042): #22 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (23042): #23 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:266:7)
E/flutter (23042): #24 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:779:19)
E/flutter (23042): #25 _StreamController._add (dart:async/stream_controller.dart:655:7)
E/flutter (23042): #26 _StreamController.add (dart:async/stream_controller.dart:597:5)
E/flutter (23042): #27 _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:1018:19)
E/flutter (23042): #28 _rootRun (dart:async/zone.dart:1180:38)
E/flutter (23042): #29 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (23042): #30 _CustomZone.runGuarded (dart:async/zone.dart:979:7)
E/flutter (23042): #31 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1019:23)
E/flutter (23042): #32 _rootRun (dart:async/zone.dart:1184:13)
E/flutter (23042): #33 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (23042): #34 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1003:23)
E/flutter (23042): #35 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (23042): #36 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter (23042): #37 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter (23042): #38 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter (23042):
Note
This error occurred on the specific email not all the emails. Also, please guide about the messageId,
and messageId is null for each MimeMessage.
According to IMAP specs, any spaces should be disregarded when reconstrucing headers that consist of multiple lines such as
Subject: here is a very long subject line that spans
several lines
However, in reality the consensus seems to be to have add a space at line breaks. So enough_mail
should act accordingly.
sendMessage function not return any response, also email not sent to the recipient.
Code
var client = SmtpClient('enough.de', isLogEnabled: true);
await client.connectToServer('smtp.domain.com', 465, isSecure: true);
var loginResponse = await client.login(username, password);
if (loginResponse.isOkStatus) {
var builder = MessageBuilder.buildSimpleTextMessage(MailAddress(sender, from), [MailAddress(recipient, to)], composeEmail, subject: subject);
var sendResponse = await client.sendMessage(builder, false);
print('message sent: ${sendResponse.message}');
}
I have a problem internalDate and date is null
message.internalDate
flutter: S: a3 OK Success
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
flutter: internalDate: null
This is just for completing IMAP4 support as the capabilities are also returned by LOGIN.
Compare https://tools.ietf.org/html/rfc3501#section-6.1.1
The SORT and THREAD extensions to the [IMAP] protocol provide a means of server-based sorting and threading of messages, without requiring that the client download the necessary data to do so itself.
This is particularly useful for online clients.
Compare https://tools.ietf.org/html/rfc5256 for details.
Also consider effects of CONDSTORE as described in https://tools.ietf.org/html/rfc7162#section-3.1.9
Provide a helper method to easily reply to an existing mime message.
Currently BODY[TEXT] part specifiers in a FETCH response are ignored.
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.