-
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.
- Loading branch information
Showing
44 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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,55 @@ | ||
package peergos.email; | ||
|
||
import peergos.server.Builder; | ||
import peergos.shared.Crypto; | ||
import peergos.shared.NetworkAccess; | ||
import peergos.shared.user.UserContext; | ||
import java.net.URL; | ||
|
||
public class EmailBridge { | ||
|
||
private final UserContext context; | ||
private final SMTPMailer smtpMailer; | ||
private final EmailSender sender; | ||
private final IMAPClient imapClient; | ||
private final EmailRetriever retriever; | ||
|
||
private EmailBridge(String username, String password, String url, boolean isPublicServer | ||
, String smtpHost, int smtpPort, String smtpUsername, String smtpPassword | ||
, String imapHost, int imapPort) throws Exception{ | ||
Crypto crypto = Builder.initCrypto(); | ||
NetworkAccess network = Builder.buildJavaNetworkAccess(new URL(url), isPublicServer).get(); | ||
context = UserContext.signIn(username, password, network, crypto).get(); | ||
|
||
smtpMailer = new SMTPMailer(smtpHost, smtpPort, smtpUsername, smtpPassword); | ||
sender = new EmailSender(smtpMailer, context); | ||
imapClient = new IMAPClient(imapHost, imapPort); | ||
retriever = new EmailRetriever(imapClient, context); | ||
} | ||
|
||
private void test() { | ||
sender.sendEmails("q"); | ||
retriever.retrieveEmailsFromServer("name","notagoodone"); | ||
} | ||
|
||
public static void main(String[] args) throws Exception { | ||
String username = "bridge"; | ||
String password = "qq"; | ||
String url = "http://localhost:8000"; | ||
boolean isPublicServer = false; | ||
|
||
|
||
String smtpHost = "smtp.host.com"; | ||
int smtpPort = 25;//587; | ||
String smtpUsername = "q"; | ||
String smtpPassword = "qq"; | ||
|
||
String imapHost = "imap.server.com"; | ||
int imapPort = 993;//143;//993; | ||
|
||
EmailBridge emailBridge = new EmailBridge(username, password, url, isPublicServer | ||
, smtpHost, smtpPort, smtpUsername, smtpPassword, imapHost, imapPort); | ||
|
||
emailBridge.test(); | ||
} | ||
} |
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 @@ | ||
package peergos.email; | ||
|
||
import org.simplejavamail.api.email.*; | ||
import org.simplejavamail.converter.internal.mimemessage.MimeMessageParser; | ||
import org.simplejavamail.email.EmailBuilder; | ||
import peergos.shared.email.Attachment; | ||
import peergos.shared.email.EmailMessage; | ||
|
||
import javax.activation.DataSource; | ||
import javax.mail.Message; | ||
import javax.mail.internet.MimeMessage; | ||
import javax.mail.util.ByteArrayDataSource; | ||
import java.io.*; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
import java.util.*; | ||
import java.util.stream.Collectors; | ||
|
||
import static org.simplejavamail.api.email.CalendarMethod.CANCEL; | ||
|
||
public class EmailConverter { | ||
|
||
public static EmailMessage parseMail(MimeMessage message) { | ||
|
||
MimeMessageParser messageParser = new MimeMessageParser(); | ||
MimeMessageParser.ParsedMimeMessageComponents components = messageParser.parseMimeMessage(message); | ||
String from = components.getFromAddress().getAddress(); | ||
String subject = components.getSubject(); | ||
List<String> toAddrs = components.getToAddresses().stream().map(a -> a.getAddress()).collect(Collectors.toList()); | ||
List<String> ccAddrs = components.getCcAddresses().stream().map(a -> a.getAddress()).collect(Collectors.toList()); | ||
|
||
String plainText = components.getPlainContent(); | ||
String id = components.getMessageId(); | ||
|
||
Date sentDate = components.getSentDate(); | ||
LocalDateTime created = LocalDateTime.ofInstant(sentDate.toInstant(), ZoneId.of("UTC")); | ||
|
||
List<Attachment> attachments = new ArrayList<>(); | ||
for(Map.Entry<String, DataSource> attachment : components.getAttachmentList().entrySet()) { | ||
DataSource source = attachment.getValue(); | ||
try { | ||
String type = source.getContentType(); | ||
String name = source.getName(); | ||
String resName = attachment.getKey(); | ||
byte[] data = readResource(source.getInputStream()); | ||
attachments.add(new Attachment(name, data.length, type, data)); | ||
} catch(Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
String calendarText = components.getCalendarContent(); | ||
if (calendarText == null) { | ||
calendarText = ""; | ||
} else { | ||
String calMethod = components.getCalendarMethod(); | ||
if (calMethod.equals("CANCEL")) { | ||
calendarText = addCancelToIcalText(calendarText); | ||
} | ||
} | ||
return new EmailMessage(id, from, subject, created, | ||
toAddrs, ccAddrs, Collections.emptyList(), | ||
plainText, true, false, attachments, calendarText, | ||
Optional.empty(), Optional.empty()); | ||
} | ||
public static EmailMessage toEmailMessage(Email email) { | ||
List<Attachment> attachments = new ArrayList<>(); | ||
for(AttachmentResource res : email.getAttachments()) { | ||
DataSource source = res.getDataSource(); | ||
try { | ||
String type = source.getContentType(); | ||
String name = source.getName(); | ||
String resName = res.getName(); | ||
byte[] data = readResource(source.getInputStream()); | ||
Attachment attachment = new Attachment(name, data.length, type, data); | ||
attachments.add(attachment); | ||
} catch(Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
String calendarText = email.getCalendarText(); | ||
if (calendarText == null) { | ||
calendarText = ""; | ||
} else { | ||
CalendarMethod calMethod = email.getCalendarMethod(); | ||
if (calMethod == CANCEL) { | ||
calendarText = addCancelToIcalText(calendarText); | ||
} | ||
} | ||
|
||
Recipient from = email.getFromRecipient(); | ||
String id = email.getId(); | ||
String plainText = email.getPlainText(); | ||
Date sentDate = email.getSentDate(); | ||
LocalDateTime created = LocalDateTime.ofInstant(sentDate.toInstant(), ZoneId.of("UTC")); | ||
|
||
String subject = email.getSubject(); | ||
List<Recipient> recipients = email.getRecipients(); | ||
List<String> toAddrs = new ArrayList<>(); | ||
List<String> ccAddrs = new ArrayList<>(); | ||
for(Recipient person : recipients) { | ||
if (person.getType() == Message.RecipientType.TO) { | ||
toAddrs.add(person.getAddress()); | ||
} else if(person.getType() == Message.RecipientType.CC) { | ||
ccAddrs.add(person.getAddress()); | ||
} | ||
} | ||
return new EmailMessage(id, from.getAddress(), subject, created, | ||
toAddrs, ccAddrs, Collections.emptyList(), | ||
plainText, true, false, attachments, calendarText, | ||
Optional.empty(), Optional.empty()); | ||
} | ||
|
||
private static String addCancelToIcalText(String icalText) { | ||
String cancelledText = "STATUS:CANCELLED"; | ||
String endToken = "END:VEVENT"; | ||
int index = icalText.indexOf(endToken); | ||
if (index > 0) { | ||
return icalText.substring(0, index) | ||
+ cancelledText + "\n" | ||
+ icalText.substring(index); | ||
} else { | ||
return icalText; | ||
} | ||
} | ||
|
||
private static byte[] readResource(InputStream in) throws IOException { | ||
ByteArrayOutputStream bout = new ByteArrayOutputStream(); | ||
OutputStream gout = new DataOutputStream(bout); | ||
byte[] tmp = new byte[4096]; | ||
int r; | ||
while ((r=in.read(tmp)) >= 0) | ||
gout.write(tmp, 0, r); | ||
gout.flush(); | ||
gout.close(); | ||
in.close(); | ||
return bout.toByteArray(); | ||
} | ||
|
||
public static Email toEmail(EmailMessage email) { | ||
Collection<Recipient> toAddrs = email.to.stream() | ||
.map(a -> new Recipient(null, a, Message.RecipientType.TO)) | ||
.collect(Collectors.toList()); | ||
|
||
Collection<Recipient> ccAddrs = email.cc.stream() | ||
.map(a -> new Recipient(null, a, Message.RecipientType.TO)) | ||
.collect(Collectors.toList()); | ||
|
||
Collection<Recipient> bccAddrs = email.bcc.stream() | ||
.map(a -> new Recipient(null, a, Message.RecipientType.TO)) | ||
.collect(Collectors.toList()); | ||
|
||
EmailPopulatingBuilder builder = null; | ||
if(email.replyingToEmail.isPresent()) { | ||
builder = EmailBuilder.replyingTo(toEmail(email.replyingToEmail.get())); | ||
} else if(email.forwardingToEmail.isPresent()) { | ||
builder = EmailBuilder.forwarding(toEmail(email.forwardingToEmail.get())); | ||
} else { | ||
builder = EmailBuilder.startingBlank().fixingMessageId(email.id); | ||
} | ||
|
||
EmailPopulatingBuilder emailBuilder = builder.from(email.from) | ||
.to(toAddrs) | ||
.cc(ccAddrs) | ||
.bcc(bccAddrs) | ||
.withSubject(email.subject) | ||
.withPlainText(email.content); | ||
|
||
Date sendDate = Date.from(email.created.atZone(ZoneId.of("UTC")).toInstant()); | ||
emailBuilder.fixingSentDate(sendDate); | ||
|
||
if (email.icalEvent.length() > 0) { | ||
emailBuilder = emailBuilder.withCalendarText(CalendarMethod.REQUEST, email.icalEvent); | ||
} | ||
|
||
List<AttachmentResource> emailAttachments = email.attachments.stream() | ||
.map(a -> new AttachmentResource(a.filename, new ByteArrayDataSource(a.data, a.type))) | ||
.collect(Collectors.toList()); | ||
|
||
if (emailAttachments.size() > 0) { | ||
emailBuilder = emailBuilder.withAttachments(emailAttachments); | ||
} | ||
return emailBuilder.buildEmail(); | ||
} | ||
} |
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,73 @@ | ||
package peergos.email; | ||
|
||
import peergos.shared.email.EmailMessage; | ||
import peergos.shared.user.SocialState; | ||
import peergos.shared.user.UserContext; | ||
import peergos.shared.user.fs.AsyncReader; | ||
import peergos.shared.user.fs.FileWrapper; | ||
|
||
import javax.mail.internet.MimeMessage; | ||
import java.util.*; | ||
import java.util.function.Function; | ||
|
||
public class EmailRetriever { | ||
private final IMAPClient imapClient; | ||
private final UserContext context; | ||
|
||
public EmailRetriever(IMAPClient imapClient, UserContext context) { | ||
this.imapClient = imapClient; | ||
this.context = context; | ||
} | ||
|
||
public void retrieveEmailsFromServerForAll() { | ||
String password = ""; | ||
|
||
SocialState state = context.getSocialState().join(); | ||
Set<String> friends = state.getFriends(); | ||
|
||
for(String friend : friends) { | ||
retrieveEmailsFromServer(friend, password); | ||
} | ||
} | ||
|
||
public boolean retrieveEmailsFromServer(String username, String password) { | ||
String path = username + "/.apps/email/data/pending/inbox"; | ||
Function<MimeMessage, Boolean> upload = (msg) -> { | ||
EmailMessage email = EmailConverter.parseMail(msg); | ||
try { | ||
Optional<FileWrapper> directory = context.getByPath(path).get(); | ||
if (directory.isPresent()) { | ||
if (uploadEmail(email, directory.get(), path)) { | ||
return true; | ||
} | ||
} | ||
} catch (Exception e) { | ||
System.err.println("Error getting directory: " + path); | ||
e.printStackTrace(); | ||
} | ||
return false; | ||
}; | ||
try { | ||
imapClient.retrieveEmails(username, password, upload); | ||
return true; | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
return false; | ||
} | ||
|
||
private boolean uploadEmail(EmailMessage email, FileWrapper directory, String path) { | ||
byte[] data = email.toBytes(); | ||
try { | ||
directory.uploadOrReplaceFile(email.id + ".cbor", new AsyncReader.ArrayBacked(data), data.length | ||
, context.network, context.crypto, l -> { | ||
}, context.crypto.random.randomBytes(32)).get(); | ||
return true; | ||
} catch (Exception e) { | ||
System.err.println("Error uploading to file: " + email.id + " to directory:" + path); | ||
e.printStackTrace(); | ||
return false; | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.