-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GitBook: [master] 6 pages and one asset modified
- Loading branch information
1 parent
6d90bb1
commit ea32839
Showing
7 changed files
with
391 additions
and
2 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")); | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
Oops, something went wrong.