Skip to content

Commit

Permalink
release v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-virkus committed Jan 11, 2021
1 parent ea1d88a commit 85ec770
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 93 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 0.1.0
- Moving from response based to exceptions, compare the migration guide for details compare the migration guide in [Readme.md](https://github.com/Enough-Software/enough_mail/blob/main/README.md#Migrating) and #101 for details - specicial thanks to [Tienisto](https://github.com/Tienisto)
- Improved performance when downloading large data significantly
- High Level API now checks for SMTP START TLS support before switching to a secure connection when connected via plan sockets
- Low level SMTP API now exposes all found server capabilities
- Fix decoding bug for UTF8 8 bit encoded text
- `ImapClient.search(...)` now returns a `MessageSequence` instead just a list of integers
- High level API now supports moving messages with `MailClient.moveMessages(...)` and `MailClient.undoMoveMessages()` methods
- High level API now supports deleting messages with `MailClient.deleteMessages(...)` and `MailClient.undoDeleteMessages()` methods

## 0.0.36
- Remove spaces between two encoded words in headers
- High level API support for deleting messages and undoing it:
Expand Down
245 changes: 153 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
Experimental IMAP, POP3 and SMTP clients for Dart developers.
IMAP, POP3 and SMTP clients for Dart developers.

Available under the commercial friendly
[MPL Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL/).

## Warning: Incoming Changes to v0.0.x API

I will change the API to use exceptions rather than `Response` objects, before increasing the version of this package to `0.1.0`.
This will ease the usage in the happy sunshine cases drastically. Also compare https://github.com/Enough-Software/enough_mail/issues/101. Thanks for testing `enough_mail`!
## Installation
Add this dependency your pubspec.yaml file:

```
dependencies:
enough_mail: ^0.1.0
```
The latest version or `enough_mail` is [![enough_mail version](https://img.shields.io/pub/v/enough_mail.svg)](https://pub.dartlang.org/packages/enough_mail).


## API Documentation
Check out the full API documentation at https://pub.dev/documentation/enough_mail/latest/

## High Level API Usage

The high level API abstracts away from IMAP and POP3 details, reconnects automatically and allows to easily watch a mailbox for new messages.
A simple usage example for using the high level API:

```dart
Expand All @@ -23,31 +33,40 @@ void main() async {
await mailExample();
}
/// High level mail API example
Future<void> mailExample() async {
var email = userName + '@domain.com';
var config = await Discover.discover(email);
var account =
MailAccount.fromDiscoveredSetings('my account', email, password, config);
var mailClient = MailClient(account, isLogEnabled: true);
await mailClient.connect();
var mailboxesResponse =
await mailClient.listMailboxesAsTree(createIntermediate: false);
if (mailboxesResponse.isOkStatus) {
print(mailboxesResponse.result);
final email = '$userName@$domain';
print('discovering settings for $email...');
final config = await Discover.discover(email);
if (config == null) {
print('Unable to autodiscover settings for $email');
return;
}
print('connecting to ${config.displayName}.');
final account =
MailAccount.fromDiscoveredSettings('my account', email, password, config);
final mailClient = MailClient(account, isLogEnabled: true);
try {
await mailClient.connect();
print('connected');
final mailboxes =
await mailClient.listMailboxesAsTree(createIntermediate: false);
print(mailboxes);
await mailClient.selectInbox();
var fetchResponse = await mailClient.fetchMessages(count: 20);
if (fetchResponse.isOkStatus) {
for (var msg in fetchResponse.result) {
printMessage(msg);
}
final messages = await mailClient.fetchMessages(count: 20);
for (final msg in messages) {
printMessage(msg);
}
mailClient.eventBus.on<MailLoadEvent>().listen((event) {
print('New message at ${DateTime.now()}:');
printMessage(event.message);
});
await mailClient.startPolling();
} on MailException catch (e) {
print('High level API failed with $e');
}
mailClient.eventBus.on<MailLoadEvent>().listen((event) {
print('New message at ${DateTime.now()}:');
printMessage(event.message);
});
mailClient.startPolling();
}
```

## Low Level Usage
Expand Down Expand Up @@ -97,95 +116,84 @@ Future<void> discoverExample() async {
}
}
/// Low level IMAP API usage example
Future<void> imapExample() async {
var client = ImapClient(isLogEnabled: false);
await client.connectToServer(imapServerHost, imapServerPort,
isSecure: isImapServerSecure);
var loginResponse = await client.login(userName, password);
if (loginResponse.isOkStatus) {
var listResponse = await client.listMailboxes();
if (listResponse.isOkStatus) {
print('mailboxes: ${listResponse.result}');
}
var inboxResponse = await client.selectInbox();
if (inboxResponse.isOkStatus) {
// fetch 10 most recent messages:
var fetchResponse = await client.fetchRecentMessages(
messageCount: 10, criteria: 'BODY.PEEK[]');
if (fetchResponse.isOkStatus) {
var messages = fetchResponse.result.messages;
for (var message in messages) {
printMessage(message);
}
}
final client = ImapClient(isLogEnabled: false);
try {
await client.connectToServer(imapServerHost, imapServerPort,
isSecure: isImapServerSecure);
await client.login(userName, password);
final mailboxes = await client.listMailboxes();
print('mailboxes: $mailboxes');
await client.selectInbox();
// fetch 10 most recent messages:
final fetchResult = await client.fetchRecentMessages(
messageCount: 10, criteria: 'BODY.PEEK[]');
for (final message in fetchResult.messages) {
printMessage(message);
}
await client.logout();
} on ImapException catch (e) {
print('IMAP failed with $e');
}
}
/// Low level SMTP API example
Future<void> smtpExample() async {
var client = SmtpClient('enough.de', isLogEnabled: true);
await client.connectToServer(smtpServerHost, smtpServerPort,
isSecure: isSmtpServerSecure);
var ehloResponse = await client.ehlo();
if (!ehloResponse.isOkStatus) {
print('SMTP: unable to say helo/ehlo: ${ehloResponse.message}');
return;
}
var loginResponse = await client.login('user.name', 'password');
if (loginResponse.isOkStatus) {
var builder = MessageBuilder.prepareMultipartAlternativeMessage();
final client = SmtpClient('enough.de', isLogEnabled: true);
try {
await client.connectToServer(smtpServerHost, smtpServerPort,
isSecure: isSmtpServerSecure);
await client.ehlo();
await client.login('user.name', 'password');
final builder = MessageBuilder.prepareMultipartAlternativeMessage();
builder.from = [MailAddress('My name', '[email protected]')];
builder.to = [MailAddress('Your name', '[email protected]')];
builder.subject = 'My first message';
builder.addTextPlain('hello world.');
builder.addTextHtml('<p>hello <b>world</b></p>');
var mimeMessage = builder.buildMimeMessage();
var sendResponse = await client.sendMessage(mimeMessage);
final mimeMessage = builder.buildMimeMessage();
final sendResponse = await client.sendMessage(mimeMessage);
print('message sent: ${sendResponse.isOkStatus}');
} on SmtpException catch (e) {
print('SMTP failed with $e');
}
}
/// Low level POP3 API example
Future<void> popExample() async {
var client = PopClient(isLogEnabled: false);
await client.connectToServer(popServerHost, popServerPort,
isSecure: isPopServerSecure);
var loginResponse = await client.login(userName, password);
//var loginResponse = await client.loginWithApop(userName, password); // optional different login mechanism
if (loginResponse.isOkStatus) {
var statusResponse = await client.status();
if (statusResponse.isOkStatus) {
print(
'status: messages count=${statusResponse.result.numberOfMessages}, messages size=${statusResponse.result.totalSizeInBytes}');
var listResponse =
await client.list(statusResponse.result.numberOfMessages);
print(
'last message: id=${listResponse.result?.first?.id} size=${listResponse.result?.first?.sizeInBytes}');
var retrieveResponse =
await client.retrieve(statusResponse.result.numberOfMessages);
if (retrieveResponse.isOkStatus) {
printMessage(retrieveResponse.result);
} else {
print('last message could not be retrieved');
}
retrieveResponse =
await client.retrieve(statusResponse.result.numberOfMessages + 1);
print(
'trying to retrieve newer message succeeded: ${retrieveResponse.isOkStatus}');
}
final client = PopClient(isLogEnabled: false);
try {
await client.connectToServer(popServerHost, popServerPort,
isSecure: isPopServerSecure);
await client.login(userName, password);
// alternative login:
// await client.loginWithApop(userName, password); // optional different login mechanism
final status = await client.status();
print(
'status: messages count=${status.numberOfMessages}, messages size=${status.totalSizeInBytes}');
final messageList = await client.list(status.numberOfMessages);
print(
'last message: id=${messageList?.first?.id} size=${messageList?.first?.sizeInBytes}');
var message = await client.retrieve(status.numberOfMessages);
printMessage(message);
message = await client.retrieve(status.numberOfMessages + 1);
print('trying to retrieve newer message succeeded');
await client.quit();
} on PopException catch (e) {
print('POP failed with $e');
}
await client.quit();
}
void printMessage(MimeMessage message) {
print('from: ${message.from} with subject "${message.decodeSubject()}"');
if (!message.isTextPlainMessage()) {
print(' content-type: ${message.mediaType}');
} else {
var plainText = message.decodeTextPlainPart();
final plainText = message.decodeTextPlainPart();
if (plainText != null) {
var lines = plainText.split('\r\n');
for (var line in lines) {
final lines = plainText.split('\r\n');
for (final line in lines) {
if (line.startsWith('>')) {
// break when quoted text starts
break;
Expand All @@ -197,14 +205,67 @@ void printMessage(MimeMessage message) {
}
```

## Installation
Add this dependency your pubspec.yaml file:
## Migrating

If you have been using a 0.0.x version of the API you need to switch from evaluating responses to just getting the data and handling exceptions if something went wrong.

Old code example:
```dart
final client = ImapClient(isLogEnabled: false);
await client.connectToServer(imapServerHost, imapServerPort,
isSecure: isImapServerSecure);
final loginResponse = await client.login(userName, password);
if (loginResponse.isOkStatus) {
final listResponse = await client.listMailboxes();
if (listResponse.isOkStatus) {
print('mailboxes: ${listResponse.result}');
final inboxResponse = await client.selectInbox();
if (inboxResponse.isOkStatus) {
// fetch 10 most recent messages:
final fetchResponse = await client.fetchRecentMessages(
messageCount: 10, criteria: 'BODY.PEEK[]');
if (fetchResponse.isOkStatus) {
final messages = fetchResponse.result.messages;
for (var message in messages) {
printMessage(message);
}
}
}
}
await client.logout();
}
```
dependencies:
enough_mail: ^0.0.36

Migrated code example:
```dart
final client = ImapClient(isLogEnabled: false);
try {
await client.connectToServer(imapServerHost, imapServerPort,
isSecure: isImapServerSecure);
await client.login(userName, password);
final mailboxes = await client.listMailboxes();
print('mailboxes: ${mailboxes}');
await client.selectInbox();
// fetch 10 most recent messages:
final fetchResult = await client.fetchRecentMessages(
messageCount: 10, criteria: 'BODY.PEEK[]');
for (var message in fetchResult.messages) {
printMessage(message);
}
await client.logout();
} on ImapException catch (e) {
print('imap failed with $e');
}
```
The latest version or `enough_mail` is [![enough_mail version](https://img.shields.io/pub/v/enough_mail.svg)](https://pub.dartlang.org/packages/enough_mail).

As you can see the code is now much simpler and shorter.

Depending on which API you use there are different exceptions to handle:
* `MailException` for the high level API
* `ImapException` for the low level IMAP API
* `PopException` for the low level POP3 API
* `SmtpException` for the low level SMTP API


## Related Projects
Check out these related projects:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: enough_mail
description: IMAP, POP3 and SMTP email clients in pure Dart. Choose between a low level and a high level API for mailing.
version: 0.0.36
version: 0.1.0
homepage: https://github.com/Enough-Software/enough_mail

environment:
Expand Down

0 comments on commit 85ec770

Please sign in to comment.