Ошибка Java Mail с Session.getInstance

При попытке использовать java-почту я получаю следующее исключение:

java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger
    at javax.mail.Session.initLogger(Session.java:226)
    at javax.mail.Session.<init>(Session.java:210)
    at javax.mail.Session.getInstance(Session.java:247)
    at com.secondstory.mailsender.MailSender.createSmtpSession(MailSender.java:67)
    at com.secondstory.mailsender.MailSender.sendSimpleMessage(MailSender.java:38)
    at com.secondstory.mailsender.MailSender.generateLostPasswordEmail(MailSender.java:79)
    at com.secondstory.mailsender.MailSenderTest.shouldReturnTrueWithCredentialsSet(MailSenderTest.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 30 more

После многократного поиска (возможно, недостаточно большого размера - давайте посмотрим!) Я обнаружил, что нам нужны две банки внутри нашего maven pom, чтобы это тоже работало. Две зависимости я имеют следующие значения:

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.5.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency> 

Что-то изменилось, но я не совсем уверен, что это такое, поскольку это работало ранее. Код, который я написал там, где этот элемент выходит из строя, выглядит следующим образом:

private static Session createSmtpSession() {
    final Properties props = new Properties();
    props.setProperty("mail.host", "host");
    props.setProperty("mail.smtp.auth", "true");
    props.setProperty("mail.smtp.starttls.enable", "true");
    props.setProperty("mail.transport.protocol", "smtp");
    //props.setProperty("mail.debug", "true");

    return Session.getInstance(props, new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(
                            "username", "password");
                }
            });
}

Мне не хватает какой-либо конфигурации или она должна работать с текущей настройкой, которую у меня есть?

Спасибо

Ответы

Ответ 1

Попробуйте добавить это в Maven POM:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.5.2</version>
</dependency>

Ответ 2

Проблема в том, что вы пытаетесь использовать javax.mail-api.jar. Это не та библиотека. JavaMail - это спецификация Java EE, интерфейсы этой спецификации публикуются в том javax.mail-api-1.6.1.jar, который работает только при компиляции. Он не обеспечивает реализацию спецификации, поэтому он не работает во время выполнения.

Вам нужно использовать реализацию спецификации JavaMail во время выполнения. Справочную реализацию можно найти по адресу https://javaee.github.io/javamail/ (но есть и другие, например, серверы приложений Java EE обычно включают один).

Для javax.mail-api.jar, https://javaee.github.io/javamail/ говорит:

Только определения API JavaMail, подходящие для компиляции; использовать только с "предоставленной" областью зависимостей Maven

В частности, в вашем случае вам нужны javax.mail.jar или mailapi.jar + javax.mail.jar mailapi.jar определенных протоколов, которые вы хотите использовать. Например, mailapi.jar + smtp.jar если вам нужна только поддержка smtp.

С Maven вы можете использовать

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.1</version>
</dependency>