Search in sources :

Example 1 with Encoding

use of i2p.susi.webmail.encoding.Encoding in project i2p.i2p by i2p.

the class SMTPClient method sendMail.

/**
 *  @param body without the attachments
 *  @param attachments may be null
 *  @param boundary non-null if attachments is non-null
 *  @return success
 */
public boolean sendMail(String host, int port, String user, String pass, String sender, String[] recipients, StringBuilder body, List<Attachment> attachments, String boundary) {
    boolean mailSent = false;
    boolean ok = true;
    Writer out = null;
    try {
        socket = InternalSocket.getSocket(host, port);
    } catch (IOException e) {
        error += _t("Cannot connect") + " (" + host + ':' + port + ") : " + e.getMessage() + '\n';
        ok = false;
    }
    try {
        // AUTH ref: RFC 4954
        if (ok) {
            socket.setSoTimeout(120 * 1000);
            int result = sendCmd(null);
            if (result != 220) {
                if (result != 0)
                    error += _t("Server refused connection") + " (" + result + ")\n";
                else
                    error += _t("Cannot connect") + " (" + host + ':' + port + ")\n";
                ok = false;
            }
        }
        if (ok) {
            sendCmdNoWait("EHLO localhost");
            socket.getOutputStream().flush();
            socket.setSoTimeout(60 * 1000);
            Result r = getFullResult();
            if (r.result == 250) {
                String[] caps = DataHelper.split(r.recv, "\r");
                for (String c : caps) {
                    if (c.equals("PIPELINING")) {
                        supportsPipelining = true;
                        Debug.debug(Debug.DEBUG, "Server supports pipelining");
                    } else if (c.startsWith("SIZE ")) {
                        try {
                            maxSize = Long.parseLong(c.substring(5));
                            Debug.debug(Debug.DEBUG, "Server max size: " + maxSize);
                        } catch (NumberFormatException nfe) {
                        }
                    } else if (c.equals("8BITMIME")) {
                        // unused, see encoding/EightBit.java
                        eightBitMime = true;
                        Debug.debug(Debug.DEBUG, "Server supports 8bitmime");
                    }
                }
            } else {
                error += _t("Server refused connection") + " (" + r + ")\n";
                ok = false;
            }
        }
        if (ok && maxSize < DEFAULT_MAX_SIZE) {
            Debug.debug(Debug.DEBUG, "Rechecking with new max size");
            // recalculate whether we'll fit
            // copied from WebMail
            long total = body.length();
            if (attachments != null && !attachments.isEmpty()) {
                for (Attachment a : attachments) {
                    total += a.getSize();
                }
            }
            long binaryMax = (long) ((maxSize * 57.0d / 78) - 32 * 1024);
            if (total > binaryMax) {
                ok = false;
                error += _t("Email is too large, max is {0}", DataHelper.formatSize2(binaryMax, false) + 'B') + '\n';
            }
        }
        if (ok) {
            // RFC 4954 says AUTH must be the last but let's assume
            // that includes the user/pass on following lines
            List<SendExpect> cmds = new ArrayList<SendExpect>();
            cmds.add(new SendExpect("AUTH LOGIN", 334));
            cmds.add(new SendExpect(base64.encode(user), 334));
            cmds.add(new SendExpect(base64.encode(pass), 235));
            if (sendCmds(cmds) != 3) {
                error += _t("Login failed") + '\n';
                ok = false;
            }
        }
        if (ok) {
            List<SendExpect> cmds = new ArrayList<SendExpect>();
            cmds.add(new SendExpect("MAIL FROM: " + sender, 250));
            for (int i = 0; i < recipients.length; i++) {
                cmds.add(new SendExpect("RCPT TO: " + recipients[i], 250));
            }
            cmds.add(new SendExpect("DATA", 354));
            if (sendCmds(cmds) != cmds.size()) {
                // TODO which recipient?
                error += _t("Mail rejected") + '\n';
                ok = false;
            }
        }
        if (ok) {
            // in-memory replace, no copies
            DataHelper.replace(body, "\r\n.\r\n", "\r\n..\r\n");
            // socket.getOutputStream().write(DataHelper.getUTF8(body));
            // socket.getOutputStream().write(DataHelper.getASCII("\r\n.\r\n"));
            // Do it this way so we don't double the memory
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO-8859-1"));
            out.write(body.toString());
            // and check the max total size
            if (attachments != null && !attachments.isEmpty()) {
                for (Attachment attachment : attachments) {
                    String encodeTo = attachment.getTransferEncoding();
                    Encoding encoding = EncodingFactory.getEncoding(encodeTo);
                    if (encoding == null)
                        throw new EncodingException(_t("No Encoding found for {0}", encodeTo));
                    // ref: https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/
                    // ref: RFC 2231
                    // split Content-Disposition into 3 lines to maximize room
                    // TODO filename*0* for long names...
                    String name = attachment.getFileName();
                    String name2 = FilenameUtil.sanitizeFilename(name);
                    String name3 = FilenameUtil.encodeFilenameRFC5987(name);
                    out.write("\r\n--" + boundary + "\r\nContent-type: " + attachment.getContentType() + "\r\nContent-Disposition: attachment;\r\n\tfilename=\"" + name2 + "\";\r\n\tfilename*=" + name3 + "\r\nContent-Transfer-Encoding: " + attachment.getTransferEncoding() + "\r\n\r\n");
                    InputStream in = null;
                    try {
                        in = attachment.getData();
                        encoding.encode(in, out);
                    } finally {
                        if (in != null)
                            try {
                                in.close();
                            } catch (IOException ioe) {
                            }
                    }
                }
                out.write("\r\n--" + boundary + "--\r\n");
            }
            out.write("\r\n.\r\n");
            out.flush();
            socket.setSoTimeout(0);
            int result = sendCmd(null);
            if (result == 250)
                mailSent = true;
            else
                error += _t("Error sending mail") + " (" + result + ")\n";
        }
    } catch (IOException e) {
        error += _t("Error sending mail") + ": " + e.getMessage() + '\n';
    }
    if (!mailSent && lastResponse.length() > 0) {
        String[] lines = DataHelper.split(lastResponse, "\r");
        for (int i = 0; i < lines.length; i++) error += lines[i] + '\n';
    }
    sendCmd("QUIT", false);
    if (socket != null) {
        try {
            socket.close();
        } catch (IOException e1) {
        }
        if (out != null)
            try {
                out.close();
            } catch (IOException ioe) {
            }
    }
    return mailSent;
}
Also used : EncodingException(i2p.susi.webmail.encoding.EncodingException) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) Attachment(i2p.susi.webmail.Attachment) Encoding(i2p.susi.webmail.encoding.Encoding) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter) OutputStreamWriter(java.io.OutputStreamWriter) BufferedWriter(java.io.BufferedWriter) Writer(java.io.Writer) OutputStreamWriter(java.io.OutputStreamWriter)

Example 2 with Encoding

use of i2p.susi.webmail.encoding.Encoding in project i2p.i2p by i2p.

the class MailPart method decode.

/**
 *  @param offset 2 for sendAttachment, 0 otherwise, probably for \r\n
 *  @since 0.9.13
 */
public void decode(int offset, Buffer out) throws IOException {
    String encg = encoding;
    if (encg == null) {
        // throw new DecodingException("No encoding specified");
        Debug.debug(Debug.DEBUG, "Warning: no transfer encoding found, fallback to 7bit.");
        encg = "7bit";
    }
    Encoding enc = EncodingFactory.getEncoding(encg);
    if (enc == null)
        throw new DecodingException(_t("No encoder found for encoding \\''{0}\\''.", WebMail.quoteHTML(encg)));
    InputStream in = null;
    LimitInputStream lin = null;
    CountingOutputStream cos = null;
    Buffer dout = null;
    try {
        in = buffer.getInputStream();
        DataHelper.skip(in, buffer.getOffset() + beginBody + offset);
        lin = new LimitInputStream(in, end - beginBody - offset);
        if (decodedLength < 0) {
            cos = new CountingOutputStream(out.getOutputStream());
            dout = new OutputStreamBuffer(cos);
        } else {
            dout = out;
        }
        enc.decode(lin, dout);
    // dout.getOutputStream().flush();
    } catch (IOException ioe) {
        if (lin != null)
            Debug.debug(Debug.DEBUG, "Decode IOE at in position " + lin.getRead() + " offset " + offset, ioe);
        else if (cos != null)
            Debug.debug(Debug.DEBUG, "Decode IOE at out position " + cos.getWritten() + " offset " + offset, ioe);
        else
            Debug.debug(Debug.DEBUG, "Decode IOE", ioe);
        throw ioe;
    } finally {
        if (in != null)
            try {
                in.close();
            } catch (IOException ioe) {
            }
        ;
        if (lin != null)
            try {
                lin.close();
            } catch (IOException ioe) {
            }
        ;
        buffer.readComplete(true);
    // let the servlet do this
    // if (cos != null) try { cos.close(); } catch (IOException ioe) {};
    // if (dout != null)
    // dout.writeComplete(true);
    // out.writeComplete(true);
    }
    if (cos != null)
        decodedLength = (int) cos.getWritten();
}
Also used : MemoryBuffer(i2p.susi.util.MemoryBuffer) OutputStreamBuffer(i2p.susi.util.OutputStreamBuffer) Buffer(i2p.susi.util.Buffer) ReadBuffer(i2p.susi.util.ReadBuffer) OutputStreamBuffer(i2p.susi.util.OutputStreamBuffer) CountingOutputStream(i2p.susi.util.CountingOutputStream) LimitInputStream(i2p.susi.util.LimitInputStream) EOFOnMatchInputStream(i2p.susi.util.EOFOnMatchInputStream) InputStream(java.io.InputStream) Encoding(i2p.susi.webmail.encoding.Encoding) DecodingException(i2p.susi.webmail.encoding.DecodingException) LimitInputStream(i2p.susi.util.LimitInputStream) IOException(java.io.IOException)

Example 3 with Encoding

use of i2p.susi.webmail.encoding.Encoding in project i2p.i2p by i2p.

the class WebMail method processComposeButtons.

/**
 * process buttons of compose message dialog
 * This must be called BEFORE processStateChangeButtons so we can add the attachment before SEND
 *
 * @param sessionObject
 * @param request
 * @return new state, or null if unknown
 */
private static State processComposeButtons(SessionObject sessionObject, RequestWrapper request) {
    State state = null;
    String filename = request.getFilename(NEW_FILENAME);
    // We handle an attachment whether sending or uploading
    if (filename != null && (buttonPressed(request, NEW_UPLOAD) || buttonPressed(request, SEND))) {
        int i = filename.lastIndexOf('/');
        if (i != -1)
            filename = filename.substring(i + 1);
        i = filename.lastIndexOf('\\');
        if (i != -1)
            filename = filename.substring(i + 1);
        if (filename != null && filename.length() > 0) {
            InputStream in = null;
            OutputStream out = null;
            I2PAppContext ctx = I2PAppContext.getGlobalContext();
            File f = new File(ctx.getTempDir(), "susimail-attachment-" + ctx.random().nextLong());
            try {
                in = request.getInputStream(NEW_FILENAME);
                if (in == null)
                    throw new IOException("no stream");
                out = new SecureFileOutputStream(f);
                DataHelper.copy(in, out);
                String contentType = request.getContentType(NEW_FILENAME);
                String encodeTo;
                String ctlc = contentType.toLowerCase(Locale.US);
                if (ctlc.startsWith("text/")) {
                    encodeTo = "quoted-printable";
                    // interpret it as ISO-8859-1
                    if (!ctlc.contains("charset="))
                        contentType += "; charset=\"utf-8\"";
                } else {
                    encodeTo = "base64";
                }
                Encoding encoding = EncodingFactory.getEncoding(encodeTo);
                if (encoding != null) {
                    if (sessionObject.attachments == null)
                        sessionObject.attachments = new ArrayList<Attachment>();
                    sessionObject.attachments.add(new Attachment(filename, contentType, encodeTo, f));
                } else {
                    sessionObject.error += _t("No Encoding found for {0}", encodeTo) + '\n';
                }
            } catch (IOException e) {
                sessionObject.error += _t("Error reading uploaded file: {0}", e.getMessage()) + '\n';
                f.delete();
            } finally {
                if (in != null)
                    try {
                        in.close();
                    } catch (IOException ioe) {
                    }
                if (out != null)
                    try {
                        out.close();
                    } catch (IOException ioe) {
                    }
            }
        }
        state = State.NEW;
    } else if (sessionObject.attachments != null && buttonPressed(request, DELETE_ATTACHMENT)) {
        for (String item : getCheckedItems(request)) {
            try {
                int n = Integer.parseInt(item);
                for (int i = 0; i < sessionObject.attachments.size(); i++) {
                    Attachment attachment = sessionObject.attachments.get(i);
                    if (attachment.hashCode() == n) {
                        sessionObject.attachments.remove(i);
                        break;
                    }
                }
            } catch (NumberFormatException nfe) {
            }
        }
        state = State.NEW;
    }
    return state;
}
Also used : I2PAppContext(net.i2p.I2PAppContext) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) DecodingOutputStream(i2p.susi.util.DecodingOutputStream) WriterOutputStream(net.i2p.servlet.util.WriterOutputStream) ZipOutputStream(java.util.zip.ZipOutputStream) EscapeHTMLOutputStream(i2p.susi.util.EscapeHTMLOutputStream) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) Encoding(i2p.susi.webmail.encoding.Encoding) IOException(java.io.IOException) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) File(java.io.File)

Example 4 with Encoding

use of i2p.susi.webmail.encoding.Encoding in project i2p.i2p by i2p.

the class WebMail method sendMail.

/**
 * @param sessionObject
 * @param request
 * @return success
 */
private static boolean sendMail(SessionObject sessionObject, RequestWrapper request) {
    boolean ok = true;
    String from = request.getParameter(NEW_FROM);
    String to = request.getParameter(NEW_TO);
    String cc = request.getParameter(NEW_CC);
    String bcc = request.getParameter(NEW_BCC);
    String subject = request.getParameter(NEW_SUBJECT, _t("no subject"));
    String text = request.getParameter(NEW_TEXT, "");
    boolean fixed = Boolean.parseBoolean(Config.getProperty(CONFIG_SENDER_FIXED, "true"));
    if (fixed) {
        String domain = Config.getProperty(CONFIG_SENDER_DOMAIN, "mail.i2p");
        from = "<" + sessionObject.user + "@" + domain + ">";
    }
    ArrayList<String> toList = new ArrayList<String>();
    ArrayList<String> ccList = new ArrayList<String>();
    ArrayList<String> bccList = new ArrayList<String>();
    ArrayList<String> recipients = new ArrayList<String>();
    String sender = null;
    if (from == null || !Mail.validateAddress(from)) {
        ok = false;
        sessionObject.error += _t("Found no valid sender address.") + '\n';
    } else {
        sender = Mail.getAddress(from);
        if (sender == null || sender.length() == 0) {
            ok = false;
            sessionObject.error += _t("Found no valid address in \\''{0}\\''.", quoteHTML(from)) + '\n';
        }
    }
    ok = Mail.getRecipientsFromList(toList, to, ok);
    ok = Mail.getRecipientsFromList(ccList, cc, ok);
    ok = Mail.getRecipientsFromList(bccList, bcc, ok);
    recipients.addAll(toList);
    recipients.addAll(ccList);
    recipients.addAll(bccList);
    String bccToSelf = request.getParameter(NEW_BCC_TO_SELF);
    boolean toSelf = "1".equals(bccToSelf);
    // save preference in session
    sessionObject.bccToSelf = toSelf;
    if (toSelf)
        recipients.add(sender);
    if (toList.isEmpty()) {
        ok = false;
        sessionObject.error += _t("No recipients found.") + '\n';
    }
    Encoding qp = EncodingFactory.getEncoding("quoted-printable");
    Encoding hl = EncodingFactory.getEncoding("HEADERLINE");
    if (qp == null) {
        ok = false;
        // can't happen, don't translate
        sessionObject.error += "Internal error: Quoted printable encoder not available.";
    }
    if (hl == null) {
        ok = false;
        // can't happen, don't translate
        sessionObject.error += "Internal error: Header line encoder not available.";
    }
    long total = text.length();
    boolean multipart = sessionObject.attachments != null && !sessionObject.attachments.isEmpty();
    if (multipart) {
        for (Attachment a : sessionObject.attachments) {
            total += a.getSize();
        }
    }
    if (total > SMTPClient.BINARY_MAX_SIZE) {
        ok = false;
        sessionObject.error += _t("Email is too large, max is {0}", DataHelper.formatSize2(SMTPClient.BINARY_MAX_SIZE, false) + 'B') + '\n';
    }
    if (ok) {
        StringBuilder body = new StringBuilder(1024);
        I2PAppContext ctx = I2PAppContext.getGlobalContext();
        body.append("Date: " + RFC822Date.to822Date(ctx.clock().now()) + "\r\n");
        // todo include real names, and headerline encode them
        body.append("From: " + from + "\r\n");
        Mail.appendRecipients(body, toList, "To: ");
        Mail.appendRecipients(body, ccList, "Cc: ");
        try {
            body.append(hl.encode("Subject: " + subject.trim()));
        } catch (EncodingException e) {
            ok = false;
            sessionObject.error += e.getMessage();
        }
        String boundary = "_=" + ctx.random().nextLong();
        if (multipart) {
            body.append("MIME-Version: 1.0\r\nContent-type: multipart/mixed; boundary=\"" + boundary + "\"\r\n\r\n");
        } else {
            body.append("MIME-Version: 1.0\r\nContent-type: text/plain; charset=\"utf-8\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n");
        }
        try {
            // TODO pass the text separately to SMTP and let it pick the encoding
            if (multipart)
                body.append("--" + boundary + "\r\nContent-type: text/plain; charset=\"utf-8\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n");
            body.append(qp.encode(text));
        } catch (EncodingException e) {
            ok = false;
            sessionObject.error += e.getMessage();
        }
        // set to the StringBuilder so SMTP can replace() in place
        sessionObject.sentMail = body;
        if (ok) {
            SMTPClient relay = new SMTPClient();
            if (relay.sendMail(sessionObject.host, sessionObject.smtpPort, sessionObject.user, sessionObject.pass, sender, recipients.toArray(new String[recipients.size()]), sessionObject.sentMail, sessionObject.attachments, boundary)) {
                sessionObject.info += _t("Mail sent.");
                sessionObject.sentMail = null;
                sessionObject.clearAttachments();
            } else {
                ok = false;
                sessionObject.error += relay.error;
            }
        }
    }
    return ok;
}
Also used : SMTPClient(i2p.susi.webmail.smtp.SMTPClient) I2PAppContext(net.i2p.I2PAppContext) UnsupportedEncodingException(java.io.UnsupportedEncodingException) EncodingException(i2p.susi.webmail.encoding.EncodingException) ArrayList(java.util.ArrayList) Encoding(i2p.susi.webmail.encoding.Encoding)

Example 5 with Encoding

use of i2p.susi.webmail.encoding.Encoding in project i2p.i2p by i2p.

the class Mail method parseHeaders.

/**
 * @return all headers, to pass to MailPart, or null on error
 */
private String[] parseHeaders(InputStream in) {
    String[] headerLines = null;
    error = "";
    if (header != null) {
        boolean ok = true;
        Encoding html = EncodingFactory.getEncoding("HTML");
        if (html == null) {
            error += "HTML encoder not found.\n";
            ok = false;
        }
        Encoding hl = EncodingFactory.getEncoding("HEADERLINE");
        if (hl == null) {
            error += "Header line encoder not found.\n";
            ok = false;
        }
        if (ok) {
            try {
                EOFOnMatchInputStream eofin = new EOFOnMatchInputStream(in, HEADER_MATCH);
                MemoryBuffer decoded = new MemoryBuffer(4096);
                hl.decode(eofin, decoded);
                if (!eofin.wasFound())
                    Debug.debug(Debug.DEBUG, "EOF hit before \\r\\n\\r\\n in Mail");
                // Fixme UTF-8 to bytes to UTF-8
                headerLines = DataHelper.split(new String(decoded.getContent(), decoded.getOffset(), decoded.getLength()), "\r\n");
                for (int j = 0; j < headerLines.length; j++) {
                    String line = headerLines[j];
                    if (line.length() == 0)
                        break;
                    String hlc = line.toLowerCase(Locale.US);
                    if (hlc.startsWith("from:")) {
                        sender = line.substring(5).trim();
                        // formattedSender = getAddress( sender );
                        shortSender = sender.replace("\"", "").trim();
                        int lt = shortSender.indexOf('<');
                        if (lt > 0)
                            shortSender = shortSender.substring(0, lt).trim();
                        else if (lt < 0 && shortSender.contains("@"))
                            // add missing <> (but thunderbird doesn't...)
                            shortSender = '<' + shortSender + '>';
                        boolean trim = shortSender.length() > 45;
                        if (trim)
                            shortSender = ServletUtil.truncate(shortSender, 42).trim();
                        shortSender = html.encode(shortSender);
                        if (trim)
                            // must be after html encode
                            shortSender += "&hellip;";
                    } else if (hlc.startsWith("date:")) {
                        dateString = line.substring(5).trim();
                        long dateLong = RFC822Date.parse822Date(dateString);
                        if (dateLong > 0)
                            setDate(dateLong);
                    } else if (hlc.startsWith("subject:")) {
                        subject = line.substring(8).trim();
                        shortSubject = subject;
                        boolean trim = subject.length() > 75;
                        if (trim)
                            shortSubject = ServletUtil.truncate(subject, 72).trim();
                        shortSubject = html.encode(shortSubject);
                        if (trim)
                            // must be after html encode
                            shortSubject += "&hellip;";
                    } else if (hlc.startsWith("reply-to:")) {
                        reply = getAddress(line.substring(9).trim());
                    } else if (hlc.startsWith("to:")) {
                        ArrayList<String> list = new ArrayList<String>();
                        getRecipientsFromList(list, line.substring(3).trim(), true);
                        if (list.isEmpty()) {
                        // don't set
                        } else if (to == null) {
                            to = list.toArray(new String[list.size()]);
                        } else if (cc == null) {
                            // Susimail bug before 0.9.33, sent 2nd To line that was really Cc
                            cc = list.toArray(new String[list.size()]);
                        } else {
                            // add to the array, shouldn't happen
                            for (int i = 0; i < to.length; i++) {
                                list.add(i, to[i]);
                            }
                            to = list.toArray(new String[list.size()]);
                        }
                    } else if (hlc.startsWith("cc:")) {
                        ArrayList<String> list = new ArrayList<String>();
                        getRecipientsFromList(list, line.substring(3).trim(), true);
                        if (list.isEmpty()) {
                        // don't set
                        } else if (cc == null) {
                            cc = list.toArray(new String[list.size()]);
                        } else {
                            // add to the array, shouldn't happen
                            for (int i = 0; i < cc.length; i++) {
                                list.add(i, cc[i]);
                            }
                            cc = list.toArray(new String[list.size()]);
                        }
                    } else if (hlc.equals("x-spam-flag: yes")) {
                        // TODO trust.spam.headers config
                        isSpam = true;
                    } else if (hlc.startsWith("content-type:")) {
                        // this is duplicated in MailPart but
                        // we want to know if we have attachments, even if
                        // we haven't fetched the body
                        contentType = line.substring(13).trim();
                    } else if (hlc.startsWith("message-id:")) {
                        messageID = line.substring(11).trim();
                    }
                }
            } catch (Exception e) {
                error += "Error parsing mail header: " + e.getClass().getName() + '\n';
                Debug.debug(Debug.ERROR, "Parse error", e);
            }
        }
    }
    return headerLines;
}
Also used : MemoryBuffer(i2p.susi.util.MemoryBuffer) ArrayList(java.util.ArrayList) Encoding(i2p.susi.webmail.encoding.Encoding) EOFOnMatchInputStream(i2p.susi.util.EOFOnMatchInputStream) ParseException(java.text.ParseException) IOException(java.io.IOException)

Aggregations

Encoding (i2p.susi.webmail.encoding.Encoding)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 InputStream (java.io.InputStream)3 EOFOnMatchInputStream (i2p.susi.util.EOFOnMatchInputStream)2 MemoryBuffer (i2p.susi.util.MemoryBuffer)2 EncodingException (i2p.susi.webmail.encoding.EncodingException)2 I2PAppContext (net.i2p.I2PAppContext)2 Buffer (i2p.susi.util.Buffer)1 CountingOutputStream (i2p.susi.util.CountingOutputStream)1 DecodingOutputStream (i2p.susi.util.DecodingOutputStream)1 EscapeHTMLOutputStream (i2p.susi.util.EscapeHTMLOutputStream)1 LimitInputStream (i2p.susi.util.LimitInputStream)1 OutputStreamBuffer (i2p.susi.util.OutputStreamBuffer)1 ReadBuffer (i2p.susi.util.ReadBuffer)1 Attachment (i2p.susi.webmail.Attachment)1 DecodingException (i2p.susi.webmail.encoding.DecodingException)1 SMTPClient (i2p.susi.webmail.smtp.SMTPClient)1 BufferedWriter (java.io.BufferedWriter)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1