Невозможно подключиться к SMTP-серверу: Ошибка [Нет провайдера для SMTP] scala Spark - PullRequest
1 голос
/ 17 июня 2020

код:

object mail {

 // implicit def stringToSeq(single: String): Seq[String] = Seq(single)
  implicit def liftToOption[T](t: T): Option[T] = Some(t)

  sealed abstract class MailType
  case object Plain extends MailType
  case object Rich extends MailType
  case object MultiPart extends MailType

  case class Mail(
    from: (String, String), // (email -> name)
    to: Seq[String],
    cc: Seq[String] = Seq.empty,
    bcc: Seq[String] = Seq.empty,
    subject: String,
    message: String,
    richMessage: Option[String] = None,
    attachment: Option[(java.io.File)] = None
  )

  object send {
    def a(mail: Mail) {
      import org.apache.commons.mail._

      val format =
        if (mail.attachment.isDefined) MultiPart
        else if (mail.richMessage.isDefined) Rich
        else Plain

      val commonsMail: Email = format match {
        case Plain => new SimpleEmail().setMsg(mail.message)
        case Rich => new HtmlEmail().setHtmlMsg(mail.richMessage.get).setTextMsg(mail.message)
        case MultiPart => {
          val attachment = new EmailAttachment()
          attachment.setPath(mail.attachment.get.getAbsolutePath)
          attachment.setDisposition(EmailAttachment.ATTACHMENT)
          attachment.setName(mail.attachment.get.getName)
          new MultiPartEmail().attach(attachment).setMsg(mail.message)
        }
      }

      // TODO Set authentication from your configuration, sys properties or w/e
      commonsMail.setHostName("smtp.office365.com")
      commonsMail.setSmtpPort(587)
      commonsMail.setAuthentication("someUserName", "TestPassword")
      commonsMail.setStartTLSEnabled(true)
      // Can't add these via fluent API because it produces exceptions
      mail.to foreach (commonsMail.addTo(_))
      mail.cc foreach (commonsMail.addCc(_))
      mail.bcc foreach (commonsMail.addBcc(_))

      commonsMail.
        setFrom(mail.from._1, mail.from._2).
        setSubject(mail.subject).
        send()
    }
  }
}

Я получаю следующую ошибку:

0/06/17 05:22:32 ERROR ApplicationMaster: User class threw exception: org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.office365.com:587
org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.office365.com:587
        at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1421)
        at org.apache.commons.mail.Email.send(Email.java:1448)
        at mail$send$.a(mail.scala:56)
        at ImpressionThrottlingPattern$.main(pattern.scala:292)
        at ImpressionThrottlingPattern.main(pattern.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.spark.deploy.yarn.ApplicationMaster$$anon$4.run(ApplicationMaster.scala:721)
Caused by: javax.mail.NoSuchProviderException: No provider for smtp
        at javax.mail.Session.getProvider(Session.java:479)
        at javax.mail.Session.getTransport(Session.java:681)
        at javax.mail.Session.getTransport(Session.java:662)
        at javax.mail.Session.getTransport(Session.java:719)
        at javax.mail.Transport.send0(Transport.java:248)
        at javax.mail.Transport.send(Transport.java:124)
        at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
        ... 9 more

Я пытался проверить с помощью te lnet, активен ли используемый мной smtp-сервер. Я обнаружил, что он активен:

[root@qa-mukund mukund.sudharsan]# telnet smtp.office365.com 587
Trying xx.xx.xx.xxx...
Connected to smtp.office365.com.
Escape character is '^]'.
220 BY5PR04CA0025.outlook.office365.com Microsoft ESMTP MAIL Service ready at Wed, 17 Jun 2020 13:48:54 +0000

Вот мой файл sbt:

name := "TestMukund"
version := "1.0"
scalaVersion := "2.11.8"
val sparkVersion = "2.3.0"
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.3.0",
"org.apache.spark" %% "spark-sql" % "2.3.0",
"com.databricks" %% "spark-csv" % "1.5.0",
"com.typesafe" % "config" % "1.2.0",
"mysql" % "mysql-connector-java" % "5.1.12",
"org.apache.commons" % "commons-dbcp2" % "2.0.1",
"org.apache.commons" % "commons-email" % "1.4"
)

assemblyMergeStrategy in assembly := {
 case PathList("META-INF", xs @ _*) => MergeStrategy.discard
 case x => MergeStrategy.first
}

Я не думаю, что проблема связана с именем пользователя и паролем, поскольку об ошибке сообщает провайдер smtp сам не найден. Я очень новичок в scala и переполнении стека. Я надеюсь, что приведенной выше информации достаточно, чтобы найти root причину проблемы.

РЕДАКТИРОВАТЬ Приложение запускается с помощью команды:

spark-submit --master yarn-cluster 
             --class ImpressionThrottlingPattern 
             --name Test_MukundDBRead 
             /home/ml.user/mukund/prod/ImpressionThrottlingPatternGenerator/target/scala-2.11/TestMukund-assembly-1.0.jar

Я пробовал переопределить версию javax.mail-api версии 1.6.2, обновив файл sbt в следующее:

libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.3.0",
"org.apache.spark" %% "spark-sql" % "2.3.0",
"com.typesafe" % "config" % "1.2.0",
"mysql" % "mysql-connector-java" % "5.1.12",
"org.apache.commons" % "commons-dbcp2" % "2.0.1",
"org.apache.commons" % "commons-email" % "1.5",
)
dependencyOverrides ++= Seq(
        "javax.activation" % "activation" % "1.1.1",
        "javax.mail" % "javax.mail-api" % "1.6.2"
)

assemblyMergeStrategy in assembly := {
 case PathList("META-INF", xs @ _*) => MergeStrategy.discard
 case x => MergeStrategy.last
}

Но тоже не сработало.

Я попытался запустить команду sbt evicted и нашел вывод, содержащий следующие строки (не уверен, поможет ли это) :

[info] Here are other dependency conflicts that were resolved:
[info]  * javax.activation:activation:1.1.1 is selected over 1.1
[info]      +- org.apache.commons:commons-email:1.4               (depends on 1.1.1)
[info]      +- com.sun.mail:javax.mail:1.5.2                      (depends on 1.1)
[success] Total time: 4 s, completed Jun 18, 2020 1:10:36 AM

Ответы [ 3 ]

1 голос
/ 17 июня 2020

Ошибка связана с тем, что код не может найти / загрузить какую-либо реализацию класса Java для связи с smtp сервером. nosuchproviderexception

В пути к классам среды выполнения должно быть несколько или старая версия javamail или activation jar. Убедитесь, что вы избавились от них и у вас установлена ​​последняя версия

Для проверки дерева зависимостей для sbt sbt "inspect tree clean"

0 голосов
/ 18 июня 2020

После больших усилий я, наконец, смог решить эту проблему.

  1. Мне пришлось загрузить почту и банку активации и явно передать ее через команду spark-submit. Как
spark-submit --jars <path_to_activation_jar>,<path_to_mail_jar> <other parameters>
Изменение конфигураций в файле sbt (обратите внимание на удаление %% из предыдущего) на следующее:
val SparkVersion = "2.3.2"
scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % SparkVersion,
"org.apache.spark" % "spark-sql_2.11" % SparkVersion,
"com.typesafe" % "config" % "1.2.0",
"mysql" % "mysql-connector-java" % "5.1.12",
"org.apache.commons" % "commons-dbcp2" % "2.0.1",
"org.apache.commons" % "commons-email" % "1.4",
)

Однако мне все еще интересно, как можно автоматически загружать почту и jar активации через sbt и не передавать явно.

0 голосов
/ 17 июня 2020

Попробуйте использовать указанную ниже библиотеку в своем build.sbt, чтобы исправить эту проблему.

"org.apache.commons" % "commons-email" % "1.5"
...