10

I'd like to send mail without bothering with the SMTP-Server which is used for delivery.

So JavaMail API doesn't work for me because I have to specify a SMTP server to connect to.

I'd like the library to find out on its own which SMTP server is responsible for which email address by querying the MX record of the mail address domain.

I'm looking for something like Aspirin. Unfortunately I can't use Aspirin itself because the development stopped 2004 and the library fails to communicate with modern spam hardened servers correctly.

An embeddable version of James would do the task. But I haven't found documentation concerning whether this is possible.

Or does anyone know about other libraries I could use?

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
Eduard Wirch
  • 9,785
  • 9
  • 61
  • 73
  • I'm curious, why would you not want to use your own mail server to handle the messages and offload the work from you? – Joel Nov 07 '08 at 14:53
  • The application is installed for different customers in different environments. They're gonna send report mails to their own email address. I don't want them to use "our" email server to deliver "their" emails. – Eduard Wirch Nov 07 '08 at 15:45
  • 3
    Note that work on Aspirin seems to have restarted. It was moved to GitHub in 2009 (http://github.com/masukomi/aspirin), and a release made in September. – Todd Owen Jul 14 '10 at 04:13

3 Answers3

15

One possible solution: get the MX record on your own and use JavaMail API.

You can get the MX record using the dnsjava project:

Maven2 dependency:

<dependency>
    <groupId>dnsjava</groupId>
    <artifactId>dnsjava</artifactId>
    <version>2.0.1</version>
</dependency>

Method for MX record retrieval:

public static String getMXRecordsForEmailAddress(String eMailAddress) {
    String returnValue = null;

    try {
        String hostName = getHostNameFromEmailAddress(eMailAddress);
        Record[] records = new Lookup(hostName, Type.MX).run();
        if (records == null) { throw new RuntimeException("No MX records found for domain " + hostName + "."); }

        if (log.isTraceEnabled()) {
            // log found entries for debugging purposes
            for (int i = 0; i < records.length; i++) {
                MXRecord mx = (MXRecord) records[i];
                String targetString = mx.getTarget().toString();
                log.trace("MX-Record for '" + hostName + "':" + targetString);
            }
        }

        // return first entry (not the best solution)
        if (records.length > 0) {
            MXRecord mx = (MXRecord) records[0];
            returnValue = mx.getTarget().toString();
        }
    } catch (TextParseException e) {
        throw new RuntimeException(e);
    }

    if (log.isTraceEnabled()) {
        log.trace("Using: " + returnValue);
    }
    return returnValue;
}

private static String getHostNameFromEmailAddress(String mailAddress) throws TextParseException {
    String parts[] = mailAddress.split("@");
    if (parts.length != 2) throw new TextParseException("Cannot parse E-Mail-Address: '" + mailAddress + "'");
    return parts[1];
}

Sending mail via JavaMail code:

public static void sendMail(String toAddress, String fromAddress, String subject, String body) throws AddressException, MessagingException {
    String smtpServer = getMXRecordsForEmailAddress(toAddress);

    // create session
    Properties props = new Properties();
    props.put("mail.smtp.host", smtpServer);
    Session session = Session.getDefaultInstance(props);

    // create message
    Message msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress(fromAddress));
    msg.setRecipient(Message.RecipientType.TO, new InternetAddress(toAddress));
    msg.setSubject(subject);
    msg.setText(body);

    // send message
    Transport.send(msg);
}
Eduard Wirch
  • 9,785
  • 9
  • 61
  • 73
  • I don't think this would work for the mass case. There are no many administrators that will configure their mail server in open relay mode. You must authenticate yourself to the server.. – Lazarin Nov 07 '08 at 14:13
  • 4
    This isn't a relay scenario. We deliver the mail to the mail server which is responsible for the email address. foo@gmail.com will be delivered to gmail and gmail WILL accept the mail if it is a valid gmail address. This is how the emailing system works. – Eduard Wirch Nov 07 '08 at 15:47
  • 1
    You're right, you're not describing a relay. But, I think what Lazarin was getting at is that a spam-hardened server will ensure that the sending host is listed in an MX record for the purported sender's domain. – erickson Nov 07 '08 at 17:19
3

This is completely the wrong way to handle this.

Anyone connected to the internet will have some kind of "legit" SMTP server available to them to take the submission of email -- your ISP, your office, etc.

You WANT to leverage because they do several things for you.

1) they take your message and the responsibility to handle that message. After you drop it off, it's not your problem anymore.

2) Any mail de-spamming technologies are handled by the server. Even better, when/if those technologies change (Domain keys anyone?), the server handles it, not your code.

3) You, as a client of that sending mail system, already have whatever credentials you need to talk to that server. Main SMTP servers are locked down via authentication, IP range, etc.

4) You're not reinventing the wheel. Leverage the infrastructure you have. Are you writing an application or a mail server? Setting up mail server is an every day task that is typically simple to do. All of those casual "dumb" users on the internet have managed to get email set up.

Will Hartung
  • 115,893
  • 19
  • 128
  • 203
2

Don't.

Sending email is much more complex than it seems. Email servers excel at (or should excel at) reliable delivery.

Set up a separate email server if you need to- that will be essentially the same as implementing one in Java (I doubt you will find libraries for this task- they would be essentially complete mail servers), but much more simpler.

alex
  • 5,213
  • 1
  • 24
  • 33