Skip to content

Commit

Permalink
GitBook: [master] 6 pages and one asset modified
Browse files Browse the repository at this point in the history
  • Loading branch information
igr authored and gitbook-bot committed Sep 15, 2020
1 parent 6d90bb1 commit ea32839
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 2 deletions.
Binary file added .gitbook/assets/gmail-less.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Initial page
# Jodd Mail

Sending emails in Java should be easier. **Jodd Mail** provides some nice classes for sending and receiving emails in an easier, practical way. They are just wrappers over the standard Java Mail library.

6 changes: 5 additions & 1 deletion SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Table of contents

* [Initial page](README.md)
* [Jodd Mail](README.md)
* [Email Definition](email-definition.md)
* [Sending Emails](sending-emails.md)
* [Receiving Emails](receiving-emails.md)
* [FAQ](faq.md)

113 changes: 113 additions & 0 deletions email-definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
description: Create Emails
---

# Email Definition

An email is defined as a simple POJO bean of type `Email`. Each part of the email message can be set individually. Moreover, `Email` supports a fluent interface, so even the definition of an e-mail message would look natural.

`Email` supports plain text, HTML messages, and any combination of both. When the only text or HTML message is set, a simple email will be sent. When both text and HTML message is set, or when attachments are added, a multi-part e-mail will be sent. Actually, `Email` supports any number of separate messages to be sent as an email. Here are some examples using fluent interface.

Plain-text email:

```java
Email email = Email.create()
.from("john@jodd.org")
.to("anna@jodd.org")
.subject("Hello!")
.textMessage("A plain text message...");
```

HTML email:

```java
Email email = Email.create()
.from("john@jodd.org")
.to("anna@jodd.org")
.subject("Hello HTML!")
.htmlMessage("<b>HTML</b> message...");
```

Text and HTML email, high priority:

```java
Email email = Email.create()
.from("john@jodd.org")
.to("anna@jodd.org")
.subject("Hello!")
.textMessage("text message...")
.htmlMessage("<b>HTML</b> message...")
.priority(PRIORITY_HIGHEST);
```

### Email Addresses

All email addresses \(from, to, cc...\) may be specified in the following ways:

* only by email address, e.g.: `some.one@jodd.com`
* by personal \(display\) name and email address in one string, e.g.: `John <some.one@jodd.com>`
* by separate personal \(display\) name and email address
* by providing `EmailAddress`, a class that parses and validates emails per specification
* by providing `InternetAddress` or just `Address` instance.

Consider using personal names as it is less likely your message is going to be marked as spam ;\)

Multiple email addresses are specified using arrays or by calling methods `to()` or `cc()` multiple times:

```java
Email email = Email.create()
.from("john@jodd.org")
.to("adr1@jodd.org", "adr2@jodd.org")
.cc("xxx@bar.com")
.cc("zzz@bar.com")
.subject("Hello HTML!")
.htmlMessage("<b>HTML</b> message");
```

### Attachments

There are several attachment types that can be added:

* from a memory byte array,
* from an input stream,
* from a file,
* from generic `DataSource`.

{% hint style="warning" %}
File attachments depend on `javax.mail` content type resolution \(that might not work for you\). You can always attach files as byte or input stream attachment.
{% endhint %}

Attachments are created using the `EmailAttachment` class:

```java
.attachment(EmailAttachment.with()
.name("some name")
.content(bytesOfImage)
```

The `content()` method accepts different attachment types.

### Embedded \(inline\) attachments

A special case of attachments is _inline_ attachments. These are usually related content for HTML message, like images, that should appear inside the message, and not separate as a real attachment.

Embedding is also supported. All attachments created with the `ContentID` set will be considered as inline attachments. However, they also need to be embedded to a certain message, to form a so-called _related_ part of an email. Email clients usually require to have all inline attachments related to some message.

### Example

```java
Email email = Email.create()
.from("inf0@jodd.org")
.to("ig0r@gmail.com")
.subject("test6")
.textMessage("Hello!")
.htmlMessage(
"<html><META http-equiv=Content-Type content=\"text/html; " +
"charset=utf-8\"><body><h1>Hey!</h1><img src='cid:c.png'>" +
"<h2>Hay!</h2></body></html>")
.embeddedAttachment(EmailAttachment.with()
.content(new File("/c.png")))
.attachment(EmailAttachment.with()
.content("/b.jpg"));
```

44 changes: 44 additions & 0 deletions faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
description: Everything you always wanted to know (but were afraid to ask).
---

# FAQ

### How to parse EML files?

What if you have your emails stored in EML files? Not a problem! Use `EMLParser.create().parse()`. It accepts both file or files content as an input and returns `ReceivedEmail` of parsed EML message.

### Gmail and new messages count?

Gmail does not support the Recent flags on messages. Since the `getNewMessageCount()` method counts messages with the RECENT flags, _Jodd_ will not \(yet\) find any such messages on Gmail servers \(hence always returning value 0\).

### Can't access Gmail?

Getting the following exception when accessing Gmail:

```text
[ALERT] Please log in via your web browser:
```

Allow access for less secured apps:

![](.gitbook/assets/gmail-less.png)

### How to parse and validate an email address?

We use `RFC2822AddressParser` class to parse, clean up, and extract email addresses parsing email addresses per **RFC2822** syntax. It can be trusted to only provide authenticated results. This class has been successfully used on many billion real-world addresses, live in production environments, but it's not perfect yet, since the standard is quite complex. Unlike `InternetAddress`, this class will preserve any RFC-2047-encoding of international characters.

### I am getting an exception when receiving emails?

It may happen that email receiving fails if you have different java-mail libraries on your classpath. For example, on Apache CXF there is `geronimo-javamail_1.4_spec-1.7.1.jar` and it conflicts with the _Jodd_ _Email_.

### Is embed attachment always supposed to be inline?

Here is how we see it:

* `inline` and `content-ID` can be set separately.
* embedded images should be set using `Content-Disposition`. Of course, setting `content-ID` is required if you want to use them.
* we could not find any reference of `inline` without a `content-ID`.

The answer is Yes - embedded attachment sets both `content-ID` and `inline`.

184 changes: 184 additions & 0 deletions receiving-emails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Receiving Emails

Receiving emails is similar to sending: there are classes that encapsulate POP3 and IMAP connections, i.e. servers. Both create the same receiving session - `ReceiveMailSession` - that fetches emails and return them as an array of `ReceivedEmails`. This way you work with both POP3 and IMAP servers in the very same way.

Even the instances of the same class `ReceiveMailSession` are created by POP3 and IMAP server implementations, **not all** methods work in the same way! This difference depends on a server type. Commonly, POP3 has fewer features \(e.g. not being able to fetch all folder names for Gmail account\), while IMAP server is richer \(e.g. it supports server-side search\). {: .attn}

During receiving, all emails are fetched and returned as an array of `ReceivedEmail` objects. This is a POJO object, so its very easy to work with. It provides many helpful methods, too. Each `ReceivedEmail` also contains a list of all messages, attachments, and attached messages \(EMLs\).

### Receiving Builder

The proposed method to fetch emails is to use the builder. It is simple, powerful and you can fine-tune the receiving process. For example, you can mark or unmark some flags, select folder and so on. Here is how:

```java
session
.receive()
.markSeen()
.fromFolder("work")
.filter(...)
.get();
```

#### Convenient methods

`ReceiveMailSession` contains some legacy but convenient methods for fetching emails:

* `receiveEmail()` - returns all emails, but don't change the 'seen' flag.
* `receiveEmailAndMarkSeen()` - returns all emails and marked all messages as 'seen'.
* `receiveEmailAndDelete()` - returns all emails and mark them as 'seen' and 'deleted'.

The first method does a little trick: since `javax.mail` always set a 'seen' flag when new message is downloaded, we do set it back on 'unseen' \(if it was like that before fetching\). This way `receiveEmail()` should not change the state of your inbox.

### POP3

For POP3 connection, use `Pop3Server`:

```java
Pop3Server popServer = MailServer.create().
host("pop3.jodd.org",
auth("username", "password")
.buildPop3MailServer();

ReceiveMailSession session = popServer.createSession();
session.open();
System.out.println(session.getMessageCount());
ReceivedEmail[] emails = session.receiveEmailAndMarkSeen();
if (emails != null) {
for (ReceivedEmail email : emails) {
System.out.println("\n\n===[" + email.getMessageNumber() + "]===");

// common info
System.out.println("FROM:" + email.from());
System.out.println("TO:" + email.to()[0]);
System.out.println("SUBJECT:" + email.subject());
System.out.println("PRIORITY:" + email.priority());
System.out.println("SENT DATE:" + email.sentDate());
System.out.println("RECEIVED DATE: " + email.receiveDate());

// process messages
List messages = email.getAllMessages();
for (EmailMessage msg : messages) {
System.out.println("------");
System.out.println(msg.getEncoding());
System.out.println(msg.getMimeType());
System.out.println(msg.getContent());
}

// process attachments
List<EmailAttachment> attachments = email.getAttachments();
if (attachments != null) {
System.out.println("+++++");
for (EmailAttachment attachment : attachments) {
System.out.println("name: " + attachment.getName());
System.out.println("cid: " + attachment.getContentId());
System.out.println("size: " + attachment.getSize());
attachment.writeToFile(
new File("d:\\", attachment.getName()));
}
}
}
}
session.close();
```

### Receiving emails using SSL

Again, very simply: use the very same `ssl()` flag. Here is how it can be used to fetch email from Google:

```java
Pop3Server popServer = MailServer.create()
.host("pop.gmail.com")
.ssl(true)
.auth("username", "password")
.buildPop3MailServer();

ReceiveMailSession session = popServer.createSession();
session.open();
...
session.close();
```

### IMAP

The above example can be converted to IMAP usage very easily:

```java
ImapServer imapServer = MailServer.create()
.host("imap.gmail.com")
.ssl(true)
.auth("username", "password")
.buildImapMailServer();

ReceiveMailSession session = imapServer.createSession();
session.open();
...
session.close();
```

Can't be easier:\)
As said above, when working with IMAP server, many methods of `ReceiveMailSession` works better or... simply, just works. For example, you should be able to use following methods:
* `getUnreadMessageCount()` - to get number of un-seen messages.
* `getAllFolders()` - to receive all folders names
* server-side filtering - read the next chapter
### Receiving Envelopes
There is an option to receive only email envelopes: the header information, like `from` and `subject` but not the content of the messages. Receiving only envelopes makes things faster and it make more sense in situations when not all messages have to be received.
Each email has it's own ID that is fetched as well. Later on, you can use this ID to filter out just the messages with specific ID.

### Filtering emails

IMAP server also knows about server-side filtering of emails. There are two ways how to construct email filter, and both can be used in the same time.

The first approach is by grouping terms:

```java
filter()
.or(
filter().and(
filter().from("from"),
filter().to("to")
),
filter().not(filter().subject("subject")),
filter().from("from2")
);
```

Static method `filter()` is a factory of `EmailFilter` instances. Above filter defines the following query expressions:

```text
(from:"from" AND to:"to") OR not(subject:"subject") OR from:"from"
```

With this approach you can define boolean queries of any complexity. But there is a more fluent way to write the same query:

```java
filter()
.from("from")
.to("to")
.or()
.not()
.subject("subject")
.from("from2");
```

Here we use non-argument methods to define _the current_ boolean operator: `and()` and `or()`. All terms defined _after_ the boolean marker method us that boolean operator. Method `not()` works only for the very _next_ term definition. This way you probably can not defined some complex queries, but it should be just fine for the real-life usages.

Here is how we can use a simple filter when fetching emails:

```java
ReceivedEmail[] emails = session.receiveEmail(filter()
.flag(Flags.Flag.SEEN, false)
.subject("Hello")
);
```

This would return all unread messages with the subject equals to "Hello".

Note that for IMAP server, the search is executed by the IMAP server. This significantly speeds up the fetching process as not all messages are downloaded. Note that searching capabilities of IMAP servers may vary.

You can use the same filters on POP3 server, but keep in mind that the search is performed on the client-side, so still all messages have to be downloaded before the search is thrown.

Loading

0 comments on commit ea32839

Please sign in to comment.