diff --git a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/MailBindingConstants.java b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/MailBindingConstants.java index f31afccfa71ab..6dc437956058e 100644 --- a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/MailBindingConstants.java +++ b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/MailBindingConstants.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.mail.internal; -import java.util.Arrays; -import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -34,8 +32,8 @@ public class MailBindingConstants { public static final ThingTypeUID THING_TYPE_IMAPSERVER = new ThingTypeUID(BINDING_ID, "imap"); public static final ThingTypeUID THING_TYPE_POP3SERVER = new ThingTypeUID(BINDING_ID, "pop3"); - public static final Set SUPPORTED_THING_TYPES = new HashSet<>( - Arrays.asList(THING_TYPE_SMTPSERVER, THING_TYPE_IMAPSERVER, THING_TYPE_POP3SERVER)); + public static final Set SUPPORTED_THING_TYPES = Set.of(THING_TYPE_SMTPSERVER, THING_TYPE_IMAPSERVER, + THING_TYPE_POP3SERVER); public static final ChannelTypeUID CHANNEL_TYPE_UID_FOLDER_MAILCOUNT = new ChannelTypeUID(BINDING_ID, "mailcount"); public static final ChannelTypeUID CHANNEL_TYPE_UID_MAIL_CONTENT = new ChannelTypeUID(BINDING_ID, "content"); diff --git a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/SMTPHandler.java b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/SMTPHandler.java index fd529b15686ec..5f31ccb4dae42 100644 --- a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/SMTPHandler.java +++ b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/SMTPHandler.java @@ -19,19 +19,23 @@ import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.PatchedMailcapCommandMap; +import javax.mail.AuthenticationFailedException; import javax.mail.MessagingException; import javax.mail.Part; +import javax.mail.Session; import javax.mail.internet.MimeMultipart; -import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; +import org.apache.commons.mail.SimpleEmail; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mail.internal.action.SendMailActions; import org.openhab.binding.mail.internal.config.SMTPConfig; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.ThingHandlerService; import org.openhab.core.types.Command; @@ -45,13 +49,15 @@ * @author Jan N. Klug - Initial contribution * @author Hans-Jörg Merk - Fixed UnsupportedDataTypeException - Originally by Jan N. Klug * - Fix sending HTML/Multipart mail - Originally by Jan N. Klug + * @author Gaël L'hopital - Added session initialization for thing status check */ @NonNullByDefault public class SMTPHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(SMTPHandler.class); private final PatchedMailcapCommandMap commandMap = new PatchedMailcapCommandMap(); - private @NonNullByDefault({}) SMTPConfig config; + private String sender = ""; + private @Nullable Session session; public SMTPHandler(Thing thing) { super(thing); @@ -63,17 +69,67 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { - config = getConfigAs(SMTPConfig.class); + updateStatus(ThingStatus.UNKNOWN); - if (config.port == 0) { - if (config.security == ServerSecurity.SSL) { - config.port = 465; - } else { - config.port = 25; + scheduler.execute(this::checkConnection); + } + + private @Nullable Session checkConnection() { + Session localSession = this.session; + if (localSession != null) { + return localSession; + } + + SMTPConfig config = getConfigAs(SMTPConfig.class); + if (config.sender instanceof String confSender) { + this.sender = confSender; + } + + Email mail = new SimpleEmail(); + mail.setHostName(config.hostname); + if (!(config.username.isEmpty() || config.password.isEmpty())) { + mail.setAuthentication(config.username, config.password); + } + + int port = config.port != 0 ? config.port : config.security == ServerSecurity.SSL ? 465 : 25; + switch (config.security) { + case SSL -> { + mail.setSSLOnConnect(true); + mail.setSslSmtpPort(Integer.toString(port)); + } + case STARTTLS -> { + mail.setStartTLSEnabled(true); + mail.setStartTLSRequired(true); + mail.setSmtpPort(port); } + case PLAIN -> mail.setSmtpPort(port); + } + + try { + localSession = mail.getMailSession(); + localSession.getTransport().connect(); + } catch (AuthenticationFailedException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage()); + return null; + } catch (EmailException | MessagingException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + return null; } + this.session = localSession; updateStatus(ThingStatus.ONLINE); + return localSession; + } + + @Override + public void dispose() { + if (session instanceof Session localSession) { + try { + localSession.getTransport().close(); + } catch (MessagingException ignore) { + } + session = null; + } } /** @@ -83,58 +139,41 @@ public void initialize() { * @return true if successful, false if failed */ public boolean sendMail(Email mail) { - try { - if (mail.getFromAddress() == null) { - mail.setFrom(config.sender); - } - mail.setHostName(config.hostname); - switch (config.security) { - case SSL: - mail.setSSLOnConnect(true); - mail.setSslSmtpPort(config.port.toString()); - break; - case STARTTLS: - mail.setStartTLSEnabled(true); - mail.setStartTLSRequired(true); - mail.setSmtpPort(config.port); - break; - case PLAIN: - mail.setSmtpPort(config.port); - } - if (!config.username.isEmpty() && !config.password.isEmpty()) { - mail.setAuthenticator(new DefaultAuthenticator(config.username, config.password)); - } - - mail.buildMimeMessage(); + if (checkConnection() instanceof Session localSession) { + mail.setMailSession(localSession); - // fix command map not available - DataHandler dataHandler = mail.getMimeMessage().getDataHandler(); - dataHandler.setCommandMap(commandMap); try { - DataSource dataSource = dataHandler.getDataSource(); - Field dataField = dataSource.getClass().getDeclaredField("data"); - dataField.setAccessible(true); - Object data = dataField.get(dataSource); - if (data instanceof MimeMultipart mimeMultipart) { - for (int i = 0; i < mimeMultipart.getCount(); i++) { - Part mimePart = mimeMultipart.getBodyPart(i); - mimePart.getDataHandler().setCommandMap(commandMap); + if (mail.getFromAddress() == null) { + mail.setFrom(sender); + } + mail.buildMimeMessage(); + + // fix command map not available + DataHandler dataHandler = mail.getMimeMessage().getDataHandler(); + dataHandler.setCommandMap(commandMap); + try { + DataSource dataSource = dataHandler.getDataSource(); + Field dataField = dataSource.getClass().getDeclaredField("data"); + dataField.setAccessible(true); + Object data = dataField.get(dataSource); + if (data instanceof MimeMultipart mimeMultipart) { + for (int i = 0; i < mimeMultipart.getCount(); i++) { + Part mimePart = mimeMultipart.getBodyPart(i); + mimePart.getDataHandler().setCommandMap(commandMap); + } } + } catch (NoSuchFieldException | IllegalAccessException ignored) { } - } catch (NoSuchFieldException | IllegalAccessException ignored) { - } - mail.sendMimeMessage(); - } catch (MessagingException | EmailException e) { - Throwable cause = e.getCause(); - if (cause != null) { - logger.warn("{}", cause.toString()); - } else { - logger.warn("{}", e.getMessage()); + mail.sendMimeMessage(); + return true; + } catch (MessagingException | EmailException e) { + logger.warn("{}", e.getCause() instanceof Throwable cause ? cause.toString() : e.getMessage()); } - return false; + } else { + logger.warn("Thing {} is not ONLINE, can't send mail", thing.getUID()); } - return true; + return false; } @Override diff --git a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/config/BaseConfig.java b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/config/BaseConfig.java index 3754c61d9851e..2c910b7884865 100644 --- a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/config/BaseConfig.java +++ b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/config/BaseConfig.java @@ -24,7 +24,7 @@ @NonNullByDefault public class BaseConfig { public @Nullable String hostname; - public Integer port = 0; + public int port = 0; public String username = ""; public String password = ""; public ServerSecurity security = ServerSecurity.PLAIN;