diff --git a/src/main/java/uk/co/bigsoft/greenmail/Main.java b/src/main/java/uk/co/bigsoft/greenmail/Main.java index 0a71410..3abeb79 100644 --- a/src/main/java/uk/co/bigsoft/greenmail/Main.java +++ b/src/main/java/uk/co/bigsoft/greenmail/Main.java @@ -12,6 +12,8 @@ import uk.co.bigsoft.greenmail.http.commands.DeleteMessageCommand; import uk.co.bigsoft.greenmail.http.commands.AddUserCommand; import uk.co.bigsoft.greenmail.http.commands.DeleteUserCommand; +import uk.co.bigsoft.greenmail.http.commands.EmlExportCommand; +import uk.co.bigsoft.greenmail.http.commands.EmlImportCommand; import uk.co.bigsoft.greenmail.http.commands.ImapAllMessagesCommand; import uk.co.bigsoft.greenmail.http.commands.ImapGetInBoxCommand; import uk.co.bigsoft.greenmail.http.commands.ImapListMailBoxCommand; @@ -79,6 +81,8 @@ private static void startHttpServer(GreenMail greenMail) { app.get("/dn/:domain/to", new ListDomainMessageCommand(greenMail, "to")); app.get("/dn/:domain/cc", new ListDomainMessageCommand(greenMail, "cc")); app.get("/dn/:domain/bcc", new ListDomainMessageCommand(greenMail, "bcc")); + app.post("/import", new EmlImportCommand(greenMail)); + app.get("/export/:mailbox/:uid", new EmlExportCommand(greenMail)); if (cfg.useAccessControlAnywhere()) { System.out.println("Allow REST connections from anywhere"); diff --git a/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlExportCommand.java b/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlExportCommand.java new file mode 100644 index 0000000..abc227e --- /dev/null +++ b/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlExportCommand.java @@ -0,0 +1,32 @@ +package uk.co.bigsoft.greenmail.http.commands; + +import java.io.ByteArrayOutputStream; + +import javax.mail.internet.MimeMessage; + +import com.icegreen.greenmail.store.MailFolder; +import com.icegreen.greenmail.store.StoredMessage; +import com.icegreen.greenmail.util.GreenMail; + +import io.javalin.http.Context; + +public class EmlExportCommand extends BaseHandler { + + public EmlExportCommand(GreenMail greenMail) { + super(greenMail); + } + + @Override + public void handle(Context ctx) throws Exception { + MailFolder mailbox = utils.getMailbox(ctx, im); + long uid = utils.getUid(ctx); + StoredMessage sm = mailbox.getMessage(uid); + MimeMessage mime = sm.getMimeMessage(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + mime.writeTo(baos); + byte[] bytes = baos.toByteArray(); + ctx.result(bytes); + ctx.header("Content-Disposition", "attachment; filename=\"email.eml\""); + ctx.header("Content-Type", "text/plain; charset=utf-8"); + } +} diff --git a/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlImportCommand.java b/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlImportCommand.java new file mode 100644 index 0000000..4fdf9f7 --- /dev/null +++ b/src/main/java/uk/co/bigsoft/greenmail/http/commands/EmlImportCommand.java @@ -0,0 +1,30 @@ +package uk.co.bigsoft.greenmail.http.commands; + +import javax.mail.Session; +import javax.mail.internet.MimeMessage; + +import com.icegreen.greenmail.util.GreenMail; +import com.icegreen.greenmail.util.GreenMailUtil; +import com.icegreen.greenmail.util.ServerSetup; + +import io.javalin.http.Context; +import io.javalin.http.UploadedFile; + +public class EmlImportCommand extends BaseHandler { + + public EmlImportCommand(GreenMail greenMail) { + super(greenMail); + } + + @Override + public void handle(Context ctx) throws Exception { + ServerSetup setup = new ServerSetup(gm.getSmtp().getPort(), gm.getSmtp().getBindTo(), ServerSetup.PROTOCOL_SMTP); + setup.setServerStartupTimeout(ServerSetup.SERVER_STARTUP_TIMEOUT); + Session session = GreenMailUtil.getSession(setup); + for (UploadedFile file : ctx.uploadedFiles()) { + MimeMessage mime = new MimeMessage(session, file.getContent()); + GreenMailUtil.sendMimeMessage(mime); + } + ctx.json("OK"); + } +} diff --git a/src/main/web/src/c/GmhUrl.js b/src/main/web/src/c/GmhUrl.js index 0bf4819..4ee152d 100644 --- a/src/main/web/src/c/GmhUrl.js +++ b/src/main/web/src/c/GmhUrl.js @@ -17,7 +17,9 @@ let mappings = { DELETE_MAILBOX: '/m/:mailbox/delete', DELETE_USER: '/u/:email/delete', ADD_USER: '/u/add', - SEND_EMAIL: '/send' + SEND_EMAIL: '/send', + EML_IMPORT: '/import', + EML_EXPORT: '/export/:mailbox/:uid' } export let ServerConfig = () => { @@ -83,3 +85,12 @@ export let AddUserUrl = () => { export let SendEmailUrl = () => { return base + mappings.SEND_EMAIL } + +export let EmlImportUrl = () => { + return base + mappings.EML_IMPORT +} + +export let EmlExportUrl = (mailbox, uid) => { + let encMailbox = encodeURIComponent(mailbox) + return base + mappings.EML_EXPORT.replace(':mailbox', encMailbox).replace(':uid', uid) +} diff --git a/src/main/web/src/c/ImportEmail.js b/src/main/web/src/c/ImportEmail.js new file mode 100644 index 0000000..3a3f562 --- /dev/null +++ b/src/main/web/src/c/ImportEmail.js @@ -0,0 +1,104 @@ +import React, {Component} from 'react' +import DialogTitle from '@material-ui/core/DialogTitle' +import Button from '@material-ui/core/Button' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent/DialogContent' +import axios from 'axios' +import {EmlImportUrl} from '../c/GmhUrl' +import SendIcon from '@material-ui/icons/Send' +import {ValidatorForm} from 'react-material-ui-form-validator' +import Typography from '@material-ui/core/Typography' +import CloseIcon from '@material-ui/icons/Close' +import PublishIcon from '@material-ui/icons/Publish' +import {Tooltip} from '@material-ui/core' + +class ImportEmail extends Component{ + + constructor(props){ + super(props) + this.state = { + openEmailDialog: false, + errorMessage: '', + file: null + } + } + + openDialog = () => { + this.setState({ + openEmailDialog: true + }) + } + + sendEmail = () => { + let url = EmlImportUrl() + let formData = new FormData(); + formData.append("email", this.state.file); + axios.post(url,formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }).then( res => { + this.closeDialog() + this.props.reload() + }, (error) => { + this.setState({ + errorMessage: error.toString() + }) + }) + } + + closeDialog = () => { + this.setState({ + openEmailDialog: false + }) + } + + handleChange = (event) => { + if (event.target.files) { + this.setState({ + file : event.target.files[0] + }) + } + } + + render(){ + return ( + + + + + + + + Import Email from .eml file + + + + + {this.state.errorMessage} + + + + + + + + + + + + + + ) + } +} + +export default ImportEmail \ No newline at end of file diff --git a/src/main/web/src/c/MessagesTable.js b/src/main/web/src/c/MessagesTable.js index 969eff7..0f4e75c 100644 --- a/src/main/web/src/c/MessagesTable.js +++ b/src/main/web/src/c/MessagesTable.js @@ -10,6 +10,7 @@ import RefreshIcon from '@material-ui/icons/Refresh' import {Tooltip} from '@material-ui/core' import Card from '@material-ui/core/Card' import ComposeEmailDialog from './ComposeEmailDialog' +import ImportEmail from './ImportEmail' function MessagesTable(props) { @@ -21,6 +22,8 @@ function MessagesTable(props) {
+ + +