enough_mail 0.0.16

  • Readme
  • Changelog
  • Example
  • Installing
  • 81

An experimental IMAP and SMTP client for Dart developers.

Available under the commercial friendly MPL Mozilla Public License 2.0.

Usage #

A simple usage example:

import 'dart:io';
import 'package:enough_mail/enough_mail.dart';

void main() async {
  await imapExample();
  await smtpExample();
  exit(0);
}

Future<void> imapExample() async {
  var client = ImapClient(isLogEnabled: false);
  await client.connectToServer('imap.domain.com', 993, isSecure: true);
  var loginResponse = await client.login('user.name', '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) {
        for (var message in fetchResponse.result) {
          print(
              'from: ${message.from} with subject "${message.decodeSubject()}"');
          if (!message.isPlainTextMessage()) {
            print(' content-type: ${message.mediaType}');
          } else {
            var plainText = message.decodePlainTextPart();
            if (plainText != null) {
              var lines = plainText.split('\r\n');
              for (var line in lines) {
                if (line.startsWith('>')) {
                  // break when quoted text starts
                  break;
                }
                print(line);
              }
            }
          }
        }
      }
    }
    await client.logout();
  }
}

Future<void> smtpExample() async {
  var client = SmtpClient('enough.de', isLogEnabled: false);
  await client.connectToServer('smtp.domain.com', 465, isSecure: true);
  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();
    builder.from = [MailAddress('My name', 'sender@domain.com')];
    builder.to = [MailAddress('Your name', 'recipient@domain.com')];
    builder.subject = 'My first message';
    builder.addPlainText('hello world.');
    builder.addHtmlText('<p>hello <b>world</b></p>');
    var mimeMessage = builder.buildMimeMessage();
    var sendResponse = await client.sendMessage(mimeMessage);
    print('message sent: ${sendResponse.isFailedStatus}');
  }
}

Installation #

Add this dependency your pubspec.yaml file:

dependencies:
  enough_mail: ^0.0.16

The latest version or enough_mail is enough_mail version.

Features and bugs #

Please file feature requests and bugs at the issue tracker.

Want to contribute? Please check out contribute.

Done #

Supported encodings #

Character encodings:

  • ASCII (7bit)
  • UTF-8 (uft8, 8bit)
  • ISO-8859-1 (latin-1)

Transfer encodings:

To do #

Develop and Contribute #

  • To start check out the package and then run pub run test to run all tests.
  • Public facing library classes are in lib, lib/imap and lib/smtp.
  • Private classes are in lib/src.
  • Test cases are in test.
  • Please file a pull request for each improvement/fix that you are create - your contributions are welcome.
  • Check out https://github.com/enough-Software/enough_mail/contribute for good first issues.

0.0.16 #

  • Adding 'name' parameter with quotes to 'Content-Type' header when adding a file

0.0.15 #

  • Adding 'name' parameter to 'Content-Type' header when adding a file

0.0.14 #

  • Save messages to the server with ImapClient.appendMessage().
  • Store message flags using the ImapClient.store() method or use one of the mark-methods like markFlagged() or markSeen().
  • Copy message(s) using ImapClient.copy().
  • Copy, fetch, store or search message with UIDs using ImapClient.uidCopy(), uidStore(), etc.
  • Remove messages marked with the \Deleted flag using ImapClient.expunge()
  • Authenticate via OAUTH 2.0 using ImapClient.authenticateWithOAuth2() (AUTH=XOAUTH2) or authenticateWithOAuthBearer() (AUTH=OAUTHBEARER).
  • You can now switch to TLS using ImapClient.startTls().
  • Query the capabilities using the ImapClient.capability() call.
  • Let the server do some housekeeping using the ImapClient.check() method.

0.0.13 #

  • Forward complex messages with MessageBuilder.prepareForwardMessage(), too (issue #24)

0.0.12 #

  • Forward messages with MessageBuilder.prepareForwardMessage()

0.0.11 #

  • Adding simple reply generation with MessageBuilder.prepareReplyToMessage() (issue #25)
  • Improvement for adding larger files (issue #28)

0.0.10 #

  • Fix for message sending via SMTP (issue #27)

0.0.9 #

  • Introducing MessageBuilder for easy mime message creation
  • Adapted example

0.0.8 #

  • Ease access to text contents of a mime message
  • Adapted example

0.0.7 #

  • Parse MIME messages using MimeMessage.parse()
  • Handle content encodings more reliably

0.0.6 #

  • Supporting ASCII character character encodings and padding BASE64 headers if required

0.0.5 #

  • Addressed health and syntax recommendations

0.0.4 #

0.0.3 #

  • Always end lines with \r\n when communicating either with SMTP or IMAP server, parse iso-8859-1 encoded headers

0.0.2 #

  • Cleaning architecture, adding support for BODY[HEADER.FIELDS] messages

0.0.1 #

  • Initial alpha version

example/enough_mail_example.dart

import 'dart:io';
import 'package:enough_mail/enough_mail.dart';

void main() async {
  await imapExample();
  await smtpExample();
  exit(0);
}

Future<void> imapExample() async {
  var client = ImapClient(isLogEnabled: false);
  await client.connectToServer('imap.domain.com', 993, isSecure: true);
  var loginResponse = await client.login('user.name', '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) {
        for (var message in fetchResponse.result) {
          print(
              'from: ${message.from} with subject "${message.decodeSubject()}"');
          if (!message.isPlainTextMessage()) {
            print(' content-type: ${message.mediaType}');
          } else {
            var plainText = message.decodePlainTextPart();
            if (plainText != null) {
              var lines = plainText.split('\r\n');
              for (var line in lines) {
                if (line.startsWith('>')) {
                  // break when quoted text starts
                  break;
                }
                print(line);
              }
            }
          }
        }
      }
    }
    await client.logout();
  }
}

Future<void> smtpExample() async {
  var client = SmtpClient('enough.de', isLogEnabled: true);
  await client.connectToServer('smtp.domain.com', 465, isSecure: true);
  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();
    builder.from = [MailAddress('My name', 'sender@domain.com')];
    builder.to = [MailAddress('Your name', 'recipient@domain.com')];
    builder.subject = 'My first message';
    builder.addPlainText('hello world.');
    builder.addHtmlText('<p>hello <b>world</b></p>');
    var mimeMessage = builder.buildMimeMessage();
    var sendResponse = await client.sendMessage(mimeMessage);
    print('message sent: ${sendResponse.isFailedStatus}');
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  enough_mail: ^0.0.16

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:enough_mail/enough_mail.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
66
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
81
Learn more about scoring.

We analyzed this package on Jul 4, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13

Analysis suggestions

Package not compatible with runtime flutter-web on web

Because of the import of dart:io via the import chain package:enough_mail/enough_mail.dartpackage:enough_mail/message_builder.dartdart:io

Package not compatible with runtime web

Because of the import of dart:io via the import chain package:enough_mail/enough_mail.dartpackage:enough_mail/message_builder.dartdart:io

Health suggestions

Fix lib/codecs/date_codec.dart. (-1 points)

Analysis of lib/codecs/date_codec.dart reported 2 hints:

line 290 col 11: Two keys in a map literal shouldn't be equal.

line 459 col 11: Two keys in a map literal shouldn't be equal.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
event_bus ^1.1.1 1.1.1
intl ^0.16.1 0.16.1
Transitive dependencies
path 1.7.0
Dev dependencies
pedantic ^1.9.0
test ^1.6.0