added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.mail-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-mail" description="Mail Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle dependency="true">mvn:com.sun.mail/javax.mail/1.6.2</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.mail/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.action;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link ISendMailActions} interface defines rule actions for sending mail
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public interface ISendMailActions {
Boolean sendMail(@Nullable String recipient, @Nullable String subject, @Nullable String text,
@Nullable List<String> urlStringList);
Boolean sendHtmlMail(@Nullable String recipient, @Nullable String subject, @Nullable String html,
@Nullable List<String> urlStringList);
}

View File

@@ -0,0 +1,236 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.action;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import javax.mail.internet.AddressException;
import org.apache.commons.mail.EmailException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mail.internal.MailBuilder;
import org.openhab.binding.mail.internal.SMTPHandler;
import org.openhab.core.automation.annotation.ActionInput;
import org.openhab.core.automation.annotation.ActionOutput;
import org.openhab.core.automation.annotation.RuleAction;
import org.openhab.core.thing.binding.ThingActions;
import org.openhab.core.thing.binding.ThingActionsScope;
import org.openhab.core.thing.binding.ThingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link SendMailActions} class defines rule actions for sending mail
*
* @author Jan N. Klug - Initial contribution
*/
@ThingActionsScope(name = "mail")
@NonNullByDefault
public class SendMailActions implements ThingActions, ISendMailActions {
private final Logger logger = LoggerFactory.getLogger(SendMailActions.class);
private @Nullable SMTPHandler handler;
@RuleAction(label = "Send Text Mail", description = "sends a text mail")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject,
@ActionInput(name = "text") @Nullable String text) {
return sendMail(recipient, subject, text, new ArrayList<>());
}
@RuleAction(label = "Send Text Mail", description = "sends a text mail with URL attachment")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject, @ActionInput(name = "text") @Nullable String text,
@ActionInput(name = "url") @Nullable String urlString) {
List<String> urlList = new ArrayList<>();
if (urlString != null) {
urlList.add(urlString);
}
return sendMail(recipient, subject, text, urlList);
}
@Override
@RuleAction(label = "Send Text Mail", description = "sends a text mail with several URL attachments")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject, @ActionInput(name = "text") @Nullable String text,
@ActionInput(name = "urlList") @Nullable List<String> urlStringList) {
if (recipient == null) {
logger.warn("Cannot send mail as recipient is missing.");
return false;
}
try {
MailBuilder builder = new MailBuilder(recipient);
if (subject != null && !subject.isEmpty()) {
builder.withSubject(subject);
}
if (text != null && !text.isEmpty()) {
builder.withText(text);
}
if (urlStringList != null) {
for (String urlString : urlStringList) {
builder.withURLAttachment(urlString);
}
}
final SMTPHandler handler = this.handler;
if (handler == null) {
logger.info("Handler is null, cannot send mail.");
return false;
} else {
return handler.sendMail(builder.build());
}
} catch (AddressException | MalformedURLException | EmailException e) {
logger.warn("Could not send mail: {}", e.getMessage());
return false;
}
}
public static boolean sendMail(@Nullable ThingActions actions, @Nullable String recipient, @Nullable String subject,
@Nullable String text) {
return SendMailActions.sendMail(actions, recipient, subject, text, new ArrayList<>());
}
public static boolean sendMail(@Nullable ThingActions actions, @Nullable String recipient, @Nullable String subject,
@Nullable String text, @Nullable String urlString) {
List<String> urlList = new ArrayList<>();
if (urlString != null) {
urlList.add(urlString);
}
return SendMailActions.sendMail(actions, recipient, subject, text, urlList);
}
public static boolean sendMail(@Nullable ThingActions actions, @Nullable String recipient, @Nullable String subject,
@Nullable String text, @Nullable List<String> urlStringList) {
return invokeMethodOf(actions).sendMail(recipient, subject, text, urlStringList);
}
@RuleAction(label = "Send HTML Mail", description = "sends a HTML mail")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendHtmlMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject,
@ActionInput(name = "html") @Nullable String html) {
return sendHtmlMail(recipient, subject, html, new ArrayList<>());
}
@RuleAction(label = "Send HTML Mail", description = "sends a HTML mail with URL attachment")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendHtmlMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject, @ActionInput(name = "html") @Nullable String html,
@ActionInput(name = "url") @Nullable String urlString) {
List<String> urlList = new ArrayList<>();
if (urlString != null) {
urlList.add(urlString);
}
return sendHtmlMail(recipient, subject, html, urlList);
}
@Override
@RuleAction(label = "Send HTML Mail", description = "sends a HTML mail with several URL attachments")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendHtmlMail(
@ActionInput(name = "recipient") @Nullable String recipient,
@ActionInput(name = "subject") @Nullable String subject, @ActionInput(name = "html") @Nullable String html,
@ActionInput(name = "urlList") @Nullable List<String> urlStringList) {
if (recipient == null) {
logger.warn("Cannot send mail as recipient is missing.");
return false;
}
try {
MailBuilder builder = new MailBuilder(recipient);
if (subject != null && !subject.isEmpty()) {
builder.withSubject(subject);
}
if (html != null && !html.isEmpty()) {
builder.withHtml(html);
}
if (urlStringList != null) {
for (String urlString : urlStringList) {
builder.withURLAttachment(urlString);
}
}
final SMTPHandler handler = this.handler;
if (handler == null) {
logger.warn("Handler is null, cannot send mail.");
return false;
} else {
return handler.sendMail(builder.build());
}
} catch (AddressException | MalformedURLException | EmailException e) {
logger.warn("Could not send mail: {}", e.getMessage());
return false;
}
}
public static boolean sendHtmlMail(@Nullable ThingActions actions, @Nullable String recipient,
@Nullable String subject, @Nullable String html) {
return SendMailActions.sendHtmlMail(actions, recipient, subject, html, new ArrayList<>());
}
public static boolean sendHtmlMail(@Nullable ThingActions actions, @Nullable String recipient,
@Nullable String subject, @Nullable String html, @Nullable String urlString) {
List<String> urlList = new ArrayList<>();
if (urlString != null) {
urlList.add(urlString);
}
return SendMailActions.sendHtmlMail(actions, recipient, subject, html, urlList);
}
public static boolean sendHtmlMail(@Nullable ThingActions actions, @Nullable String recipient,
@Nullable String subject, @Nullable String html, @Nullable List<String> urlStringList) {
return invokeMethodOf(actions).sendHtmlMail(recipient, subject, html, urlStringList);
}
@Override
public void setThingHandler(@Nullable ThingHandler handler) {
if (handler instanceof SMTPHandler) {
this.handler = (SMTPHandler) handler;
}
}
@Override
public @Nullable ThingHandler getThingHandler() {
return this.handler;
}
private static ISendMailActions invokeMethodOf(@Nullable ThingActions actions) {
if (actions == null) {
throw new IllegalArgumentException("actions cannot be null");
}
if (actions.getClass().getName().equals(SendMailActions.class.getName())) {
if (actions instanceof ISendMailActions) {
return (ISendMailActions) actions;
} else {
return (ISendMailActions) Proxy.newProxyInstance(ISendMailActions.class.getClassLoader(),
new Class[] { ISendMailActions.class }, (Object proxy, Method method, Object[] args) -> {
Method m = actions.getClass().getDeclaredMethod(method.getName(),
method.getParameterTypes());
return m.invoke(actions, args);
});
}
}
throw new IllegalArgumentException("Actions is not an instance of SendMailActions");
}
}

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.type.ChannelTypeUID;
/**
* The {@link MailBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class MailBindingConstants {
private static final String BINDING_ID = "mail";
public static final ThingTypeUID THING_TYPE_SMTPSERVER = new ThingTypeUID(BINDING_ID, "smtp");
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<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
Arrays.asList(THING_TYPE_SMTPSERVER, THING_TYPE_IMAPSERVER, THING_TYPE_POP3SERVER));
public static final ChannelTypeUID CHANNEL_TYPE_UID_FOLDER_MAILCOUNT = new ChannelTypeUID(BINDING_ID, "mailcount");
}

View File

@@ -0,0 +1,203 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.activation.FileDataSource;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailConstants;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link MailBuilder} class provides a builder for an mail.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class MailBuilder {
private String sender = "";
private List<InternetAddress> recipients = new ArrayList<>();
private List<URL> attachmentURLs = new ArrayList<>();
private List<File> attachmentFiles = new ArrayList<>();
private String subject = "(no subject)";
private String text = "";
private String html = "";
/**
* Create a new MailBuilder
*
* @param recipients comma separated sequence of addresses (must follow RFC822 syntax)
* @throws AddressException on invalid recipient address
*/
public MailBuilder(String recipients) throws AddressException {
this.recipients.addAll(Arrays.asList(InternetAddress.parse(recipients)));
}
/**
* Add one or more recipients
*
* @param recipients comma separated sequence of addresses (must follow RFC822 syntax)
* @return a MailBuilder
* @throws AddressException on invalid recipient address
*/
public MailBuilder withRecipients(String recipients) throws AddressException {
this.recipients.addAll(Arrays.asList(InternetAddress.parse(recipients)));
return this;
}
/**
* Set the sender address
*
* @param sender address (must follow RFC822 syntax)
* @return a MailBuilder
*/
public MailBuilder withSender(String sender) {
this.sender = sender;
return this;
}
/**
* Set the mail subject
*
* @param subject String containing the subject
* @return a MailBuilder
*/
public MailBuilder withSubject(String subject) {
this.subject = subject;
return this;
}
/**
* Set the plain text content
*
* @param text String containing the text
* @return a MailBuilder
*/
public MailBuilder withText(String text) {
this.text = text;
return this;
}
/**
* Set the HTML content
*
* @param html a String containing HTML (syntax not checked)
* @return a MailBuilder
*/
public MailBuilder withHtml(String html) {
this.html = html;
return this;
}
/**
* Attach an URL
*
* @param urlString the URL as String
* @return a MailBuilder
* @throws MalformedURLException if url has invalid format
*/
public MailBuilder withURLAttachment(String urlString) throws MalformedURLException {
attachmentURLs.add(new URL(urlString));
return this;
}
/**
* Attach a file
*
* @param path String with path to local file
* @return a MailBuilder
*/
public MailBuilder withFileAttachment(String path) {
attachmentFiles.add(new File(path));
return this;
}
/**
* Build the Mail
*
* @return instance of Email
* @throws EmailException if something goes wrong
*/
public Email build() throws EmailException {
Email mail;
if (attachmentURLs.isEmpty() && attachmentFiles.isEmpty() && html.isEmpty()) {
// text mail without attachments
mail = new SimpleEmail();
mail.setCharset(EmailConstants.UTF_8);
if (!text.isEmpty()) {
mail.setMsg(text);
}
} else if (html.isEmpty()) {
// text mail with attachments
MultiPartEmail multipartMail = new MultiPartEmail();
multipartMail.setCharset(EmailConstants.UTF_8);
if (!text.isEmpty()) {
multipartMail.setMsg(text);
}
for (File file : attachmentFiles) {
multipartMail.attach(file);
}
for (URL url : attachmentURLs) {
String fileName = url.toString().replaceFirst(".*/([^/?]+).*", "$1");
multipartMail.attach(url, fileName, fileName, EmailAttachment.ATTACHMENT);
}
mail = multipartMail;
} else {
// html email
HtmlEmail htmlMail = new HtmlEmail();
htmlMail.setCharset(EmailConstants.UTF_8);
if (!text.isEmpty()) {
// alternate text supplied
htmlMail.setTextMsg(text);
htmlMail.setHtmlMsg(html);
} else {
htmlMail.setMsg(html);
}
for (File file : attachmentFiles) {
htmlMail.attach(new FileDataSource(file), "", "");
}
for (URL url : attachmentURLs) {
EmailAttachment attachment = new EmailAttachment();
attachment.setURL(url);
attachment.setDisposition(EmailAttachment.ATTACHMENT);
htmlMail.attach(attachment);
}
mail = htmlMail;
}
mail.setTo(recipients);
mail.setSubject(subject);
if (!sender.isEmpty()) {
mail.setFrom(sender);
}
return mail;
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
/**
* The {@link MailCountChannelType} enum for folder mail count type
*
* @author Jan N. Klug - Initial contribution
*/
public enum MailCountChannelType {
UNREAD,
TOTAL
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
import static org.openhab.binding.mail.internal.MailBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Component;
/**
* The {@link MailHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.mail", service = ThingHandlerFactory.class)
public class MailHandlerFactory extends BaseThingHandlerFactory {
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (THING_TYPE_SMTPSERVER.equals(thingTypeUID)) {
return new SMTPHandler(thing);
} else if (THING_TYPE_IMAPSERVER.equals(thingTypeUID) || THING_TYPE_POP3SERVER.equals(thingTypeUID)) {
return new POP3IMAPHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,146 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
import static org.openhab.binding.mail.internal.MailBindingConstants.CHANNEL_TYPE_UID_FOLDER_MAILCOUNT;
import java.util.Properties;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FlagTerm;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mail.internal.config.POP3IMAPChannelConfig;
import org.openhab.binding.mail.internal.config.POP3IMAPConfig;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.thing.Channel;
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.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link POP3IMAPHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class POP3IMAPHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(POP3IMAPHandler.class);
private @NonNullByDefault({}) POP3IMAPConfig config;
private @Nullable ScheduledFuture<?> refreshTask;
private final String baseProtocol;
private String protocol = "imap";
public POP3IMAPHandler(Thing thing) {
super(thing);
baseProtocol = thing.getThingTypeUID().getId(); // pop3 or imap
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
@Override
public void initialize() {
config = getConfigAs(POP3IMAPConfig.class);
protocol = baseProtocol;
if (config.security == ServerSecurity.SSL) {
protocol = protocol.concat("s");
}
if (config.port == 0) {
switch (protocol) {
case "imap":
config.port = 143;
break;
case "imaps":
config.port = 993;
break;
case "pop3":
config.port = 110;
break;
case "pop3s":
config.port = 995;
break;
default:
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
return;
}
}
refreshTask = scheduler.scheduleWithFixedDelay(this::refresh, 0, config.refresh, TimeUnit.SECONDS);
updateStatus(ThingStatus.ONLINE);
}
@SuppressWarnings("null")
@Override
public void dispose() {
if (refreshTask != null) {
if (!refreshTask.isCancelled()) {
refreshTask.cancel(true);
}
}
}
private void refresh() {
Properties props = new Properties();
props.setProperty("mail." + baseProtocol + ".starttls.enable", "true");
props.setProperty("mail.store.protocol", protocol);
Session session = Session.getInstance(props);
try (Store store = session.getStore()) {
store.connect(config.hostname, config.port, config.username, config.password);
for (Channel channel : thing.getChannels()) {
if (CHANNEL_TYPE_UID_FOLDER_MAILCOUNT.equals(channel.getChannelTypeUID())) {
final POP3IMAPChannelConfig channelConfig = channel.getConfiguration()
.as(POP3IMAPChannelConfig.class);
final String folderName = channelConfig.folder;
if (folderName == null || folderName.isEmpty()) {
logger.info("missing or empty folder name in channel {}", channel.getUID());
} else {
try (Folder mailbox = store.getFolder(folderName)) {
mailbox.open(Folder.READ_ONLY);
if (channelConfig.type == MailCountChannelType.TOTAL) {
updateState(channel.getUID(), new DecimalType(mailbox.getMessageCount()));
} else {
updateState(channel.getUID(), new DecimalType(
mailbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)).length));
}
} catch (MessagingException e) {
throw e;
}
}
}
}
} catch (MessagingException e) {
logger.info("error when trying to refresh IMAP: {}", e.getMessage());
}
}
}

View File

@@ -0,0 +1,111 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.mail.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.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link SMTPHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class SMTPHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(SMTPHandler.class);
private @NonNullByDefault({}) SMTPConfig config;
public SMTPHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
@Override
public void initialize() {
config = getConfigAs(SMTPConfig.class);
if (config.port == 0) {
if (config.security == ServerSecurity.SSL) {
config.port = 465;
} else {
config.port = 25;
}
}
updateStatus(ThingStatus.ONLINE);
}
/**
* use this server to send a mail
*
* @param mail the Email that needs to be sent
* @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.send();
} catch (EmailException e) {
logger.warn("{}", e.getMessage());
if (e.getCause() != null) {
logger.warn("{}", e.getCause().toString());
}
return false;
}
return true;
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singletonList(SendMailActions.class);
}
}

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal;
/**
* The {@link ServerSecurity} enum contains security configuration options
*
* @author Jan N. Klug - Initial contribution
*/
public enum ServerSecurity {
PLAIN,
SSL,
STARTTLS
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mail.internal.ServerSecurity;
/**
* The {@link BaseConfig} class contains fields mapping thing configuration parameters.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class BaseConfig {
public @Nullable String hostname;
public Integer port = 0;
public String username = "";
public String password = "";
public ServerSecurity security = ServerSecurity.PLAIN;
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mail.internal.MailCountChannelType;
/**
* The {@link POP3IMAPChannelConfig} class contains fields mapping thing configuration parameters.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class POP3IMAPChannelConfig {
public @Nullable String folder;
public MailCountChannelType type = MailCountChannelType.TOTAL;
}

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link POP3IMAPConfig} class contains fields mapping thing configuration parameters.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class POP3IMAPConfig extends BaseConfig {
public int refresh = 60;
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link SMTPConfig} class contains fields mapping thing configuration parameters.
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class SMTPConfig extends BaseConfig {
public @Nullable String sender;
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="mail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>Mail Binding</name>
<description>This binding is used to access POP3, IMAP and SMTP servers.</description>
<author>Jan N. Klug</author>
</binding:binding>

View File

@@ -0,0 +1,57 @@
# binding
binding.mail.name = Mail Binding
binding.mail.description = Unterstützung von POP3, IMAP und SMTP Servern
# thing types
thing-type.mail.smtp.label = SMTP Server
thing-type.mail.smtp.description = Wird zum Versenden von E-Mails verwendet
thing-type.config.mail.smtp.sender.label = Absender
thing-type.config.mail.smtp.sender.description = Standard-Absender für E-Mails
thing-type.config.mail.smtp.hostname.label = IP-Adresse
thing-type.config.mail.smtp.hostname.description = IP-Adresse oder Hostname des SMTP Servers
thing-type.config.mail.smtp.port.label = Port
thing-type.config.mail.smtp.port.description = Standard Ports sind 25 für PLAIN/STARTTLS und 465 für SSL/TLS
thing-type.config.mail.smtp.security.label = Sicherheitsprotokoll
thing-type.config.mail.smtp.security.description = Server Sicherheitsprotokoll zur Kommunikation mit dem SMTP Server
thing-type.config.mail.smtp.username.label = Benutzer
thing-type.config.mail.smtp.username.description = Benutzer zur Authentifizierung am SMTP Server
thing-type.config.mail.smtp.password.label = Passwort
thing-type.config.mail.smtp.password.description = Passwort zur Authentifizierung am SMTP Server
thing-type.mail.imap.label = IMAP Server
thing-type.mail.imap.description = IMAP Postfach Überwachung
thing-type.config.mail.imap.hostname.label = IP-Adresse
thing-type.config.mail.imap.hostname.description = IP-Adresse oder Hostname des IMAP Servers
thing-type.config.mail.imap.port.label = Port
thing-type.config.mail.imap.port.description = Standard Ports sind 143 für PLAIN/STARTTLS und 993 für SSL/TLS
thing-type.config.mail.imap.security.label = Sicherheitsprotokoll
thing-type.config.mail.imap.security.description = Server Sicherheitsprotokoll zur Kommunikation mit dem IMAP Server
thing-type.config.mail.imap.username.label = Benutzer
thing-type.config.mail.imap.username.description = Benutzer zur Authentifizierung am IMAP Server
thing-type.config.mail.imap.password.label = Passwort
thing-type.config.mail.imap.password.description = Passwort zur Authentifizierung am IMAP Server
thing-type.config.mail.imap.refresh.label = Abfrageintervall
thing-type.config.mail.imap.refresh.description = Zeit zwischen zwei Abfragen (in s, Standard ist 60s)
thing-type.mail.pop3.label = POP3 Server
thing-type.mail.pop3.description = POP3 Postfach Überwachung
thing-type.config.mail.pop3.hostname.label = IP-Adresse
thing-type.config.mail.pop3.hostname.description = IP-Adresse oder Hostname des POP3 Servers
thing-type.config.mail.pop3.port.label = Port
thing-type.config.mail.pop3.port.description = Standard Ports sind 110 für PLAIN/STARTTLS und 995 für SSL/TLS
thing-type.config.mail.pop3.security.label = Sicherheitsprotokoll
thing-type.config.mail.pop3.security.description = Server Sicherheitsprotokoll zur Kommunikation mit dem POP3 Server
thing-type.config.mail.pop3.username.label = Benutzer
thing-type.config.mail.pop3.username.description = Benutzer zur Authentifizierung am POP3 Server
thing-type.config.mail.pop3.password.label = Passwort
thing-type.config.mail.pop3.password.description = Passwort zur Authentifizierung am POP3 Server
thing-type.config.mail.pop3.refresh.label = Abfrageintervall
thing-type.config.mail.pop3.refresh.description = Zeit zwischen zwei Abfragen (in s, Standard ist 60s)
channel-type.mail.mailcount.label = Anzahl
channel-type.mail.mailcount.description = Anzahl der E-Mails im Postfach
channel-type.config.mail.mailcount.folder.label = Postfach
channel-type.config.mail.mailcount.folder.description = Name des Postfachs auf dem Server
channel-type.config.mail.mailcount.type.label = Typ
channel-type.config.mail.mailcount.type.option.TOTAL = Gesamt
channel-type.config.mail.mailcount.type.option.UNREAD = Ungelesen

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="mail"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="smtp">
<label>SMTP Server</label>
<description>Used for sending emails via rule actions</description>
<config-description>
<parameter name="sender" type="text" required="true">
<label>Sender</label>
<description>Default sender address for mail</description>
</parameter>
<parameter name="hostname" type="text" required="true">
<label>Server Hostname</label>
</parameter>
<parameter name="port" type="text" required="false">
<label>Server Port</label>
<description>Default values are 25 for plain/STARTTLS and 465 for SSL/TLS</description>
<advanced>true</advanced>
</parameter>
<parameter name="security" type="text" required="false">
<label>SMTP Server Security Protocol</label>
<options>
<option value="PLAIN">plain</option>
<option value="STARTTLS">STARTTLS</option>
<option value="SSL">SSL/TLS</option>
</options>
<limitToOptions>true</limitToOptions>
<default>PLAIN</default>
</parameter>
<parameter name="username" type="text" required="false">
<label>SMTP Server Username</label>
</parameter>
<parameter name="password" type="text" required="false">
<label>SMTP Server Password</label>
<context>password</context>
</parameter>
</config-description>
</thing-type>
<thing-type id="imap" extensible="mailcount">
<label>IMAP Server</label>
<description>Used for receiving emails</description>
<config-description>
<parameter name="hostname" type="text" required="true">
<label>Server Hostname</label>
</parameter>
<parameter name="port" type="text" required="false">
<label>Server Port</label>
<description>Default values are 143 for plain/STARTTLS and 993 for SSL/TLS</description>
<advanced>true</advanced>
</parameter>
<parameter name="security" type="text" required="false">
<label>SMTP Server Security Protocol</label>
<options>
<option value="PLAIN">plain</option>
<option value="STARTTLS">STARTTLS</option>
<option value="SSL">SSL/TLS</option>
</options>
<limitToOptions>true</limitToOptions>
<default>PLAIN</default>
</parameter>
<parameter name="username" type="text" required="true">
<label>SMTP Server Username</label>
</parameter>
<parameter name="password" type="text" required="true">
<label>SMTP Server Password</label>
<context>password</context>
</parameter>
<parameter name="refresh" type="integer" required="false">
<label>Refresh Time for This Account in S</label>
<default>60</default>
</parameter>
</config-description>
</thing-type>
<thing-type id="pop3" extensible="mailcount">
<label>POP3 Server</label>
<description>Used for receiving emails</description>
<config-description>
<parameter name="hostname" type="text" required="true">
<label>Server Hostname</label>
</parameter>
<parameter name="port" type="text" required="false">
<label>Server Port</label>
<description>Default values are 110 for plain/STARTTLS and 995 for SSL/TLS</description>
<advanced>true</advanced>
</parameter>
<parameter name="security" type="text" required="false">
<label>SMTP Server Security Protocol</label>
<options>
<option value="PLAIN">plain</option>
<option value="STARTTLS">STARTTLS</option>
<option value="SSL">SSL/TLS</option>
</options>
<limitToOptions>true</limitToOptions>
<default>PLAIN</default>
</parameter>
<parameter name="username" type="text" required="true">
<label>SMTP Server Username</label>
</parameter>
<parameter name="password" type="text" required="true">
<label>SMTP Server Password</label>
<context>password</context>
</parameter>
<parameter name="refresh" type="integer" required="false">
<label>Refresh Time for This Account in S</label>
<default>60</default>
</parameter>
</config-description>
</thing-type>
<channel-type id="mailcount">
<item-type>Number</item-type>
<label>Mail Count</label>
<description>Number of emails in folder</description>
<state readOnly="true"/>
<config-description>
<parameter name="folder" type="text" required="true">
<label>Folder Name</label>
<required>true</required>
</parameter>
<parameter name="type" type="text" required="false">
<options>
<option value="UNREAD">Unread</option>
<option value="TOTAL">Total</option>
</options>
<limitToOptions>true</limitToOptions>
<default>TOTAL</default>
</parameter>
</config-description>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,92 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.mail;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
import org.junit.Test;
import org.openhab.binding.mail.internal.MailBuilder;
/**
* The {@link MailBuilderTest} class defines tests for the {@link MailBuilder} class
*
* @author Jan N. Klug - Initial contribution
*/
public class MailBuilderTest {
private static final String TEST_STRING = "test";
private static final String TEST_EMAIL = "foo@bar.zinga";
@Test(expected = AddressException.class)
public void illegalToAddressThrowsException() throws AddressException {
MailBuilder builder = new MailBuilder("foo bar.zinga");
}
@Test(expected = EmailException.class)
public void illegalFromAddressThrowsException() throws AddressException, EmailException {
Email mail = new MailBuilder("TEST_EMAIL").withSender("foo bar.zinga").build();
}
@Test(expected = MalformedURLException.class)
public void illegalURLThrowsException() throws AddressException, MalformedURLException {
MailBuilder builder = new MailBuilder("TEST_EMAIL").withURLAttachment("foo bar.zinga");
}
@Test
public void withTextOnlyReturnsSimpleEmail() throws AddressException, EmailException {
MailBuilder builder = new MailBuilder(TEST_EMAIL);
Email mail = builder.withText("boo").build();
assertThat(mail, instanceOf(SimpleEmail.class));
}
@Test
public void withURLAttachmentReturnsMultiPartEmail()
throws AddressException, EmailException, MalformedURLException {
MailBuilder builder = new MailBuilder(TEST_EMAIL);
Email mail = builder.withText("boo").withURLAttachment("http://www.openhab.org").build();
assertThat(mail, instanceOf(MultiPartEmail.class));
}
@Test
public void withHtmlReturnsHtmlEmail() throws AddressException, EmailException {
MailBuilder builder = new MailBuilder(TEST_EMAIL);
Email mail = builder.withHtml("<html>test</html>").build();
assertThat(mail, instanceOf(HtmlEmail.class));
}
@Test
public void fieldsSetInMail() throws EmailException, MessagingException, IOException {
MailBuilder builder = new MailBuilder(TEST_EMAIL);
assertEquals("(no subject)", builder.build().getSubject());
assertEquals(TEST_STRING, builder.withSubject(TEST_STRING).build().getSubject());
assertEquals(TEST_EMAIL, builder.withSender(TEST_EMAIL).build().getFromAddress().getAddress());
assertEquals(TEST_EMAIL, builder.build().getToAddresses().get(0).getAddress());
assertEquals(2, builder.withRecipients(TEST_EMAIL).build().getToAddresses().size());
}
}