From 16238fe69528ab1b0e6fb2a33540720c9caf1e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E5=82=91?= Date: Mon, 19 Dec 2022 00:46:42 +0800 Subject: [PATCH] Initial commit --- .run/RunTerminal.run.xml | 24 ++++++ README.md | 26 ++++++ build.gradle.kts | 8 +- src/main/kotlin/JMailNotify.kt | 83 ++++++++++++++++++- src/main/kotlin/PluginCommands.kt | 80 +++++++++++++++++- src/main/kotlin/PluginConfig.kt | 65 ++++++++++++++- ...t.mamoe.mirai.console.plugin.jvm.JvmPlugin | 2 +- src/test/kotlin/SendMailTest.kt | 13 ++- 8 files changed, 294 insertions(+), 7 deletions(-) create mode 100644 .run/RunTerminal.run.xml diff --git a/.run/RunTerminal.run.xml b/.run/RunTerminal.run.xml new file mode 100644 index 0000000..75e700f --- /dev/null +++ b/.run/RunTerminal.run.xml @@ -0,0 +1,24 @@ + + + + + + + true + true + false + + + \ No newline at end of file diff --git a/README.md b/README.md index e69de29..48f3917 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,26 @@ +# J Mail Notify +基于 Mirai-Console 的插件,在你的机器人上线、下线时向你发送邮件通知。 + +# 指令集 + +```shell +/jmn reload # 重载配置 +/jmn setDisabled # 设置关闭通知 +/jmn setLogin # 设置登录通知 +/jmn setLogout # 设置登出通知 +/jmn setSendTo # 设置收件人邮箱地址 +/jmn setSender # 设置SMTP发件人邮箱 +/jmn setSmtpServer # 设置SMTP服务器 +/jmn test [title] [message] # 发送测试邮件 +``` + +# 示例 +```shell +> jmn setSender me@qq.com Authorization-code +OK +> jmn setSendTo target@qq.com +OK +> jmn test +邮件已发送 +``` +![Test mail](docs/TestMail.png) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 4f97d41..34a49bc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,10 +6,16 @@ plugins { id("net.mamoe.mirai-console") version "2.13.2" } -group = "top.jie65535.mirai" +group = "top.jie65535.mirai.mailnotify" version = "0.1.0" repositories { maven("https://maven.aliyun.com/repository/public") mavenCentral() } + +dependencies { + // https://mvnrepository.com/artifact/jakarta.mail/jakarta.mail-api + implementation("jakarta.mail:jakarta.mail-api:2.0.0") + implementation("com.sun.mail:jakarta.mail:2.0.1") +} \ No newline at end of file diff --git a/src/main/kotlin/JMailNotify.kt b/src/main/kotlin/JMailNotify.kt index 29acf5e..9b61654 100644 --- a/src/main/kotlin/JMailNotify.kt +++ b/src/main/kotlin/JMailNotify.kt @@ -1,8 +1,18 @@ -package top.jie65535.mirai +package top.jie65535.mirai.mailnotify +import jakarta.mail.Authenticator +import jakarta.mail.PasswordAuthentication +import jakarta.mail.Session +import jakarta.mail.internet.InternetAddress +import jakarta.mail.internet.MimeMessage +import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin +import net.mamoe.mirai.event.events.BotOfflineEvent +import net.mamoe.mirai.event.events.BotOnlineEvent +import net.mamoe.mirai.event.globalEventChannel import net.mamoe.mirai.utils.info +import java.util.* object JMailNotify : KotlinPlugin( JvmPluginDescription( @@ -16,5 +26,76 @@ object JMailNotify : KotlinPlugin( ) { override fun onEnable() { logger.info { "Plugin loaded" } + PluginCommands.register() + PluginConfig.reload() + + // 订阅上线事件 + globalEventChannel().subscribeAlways { + if (PluginConfig.loginNotify) { + sendMail("[Mirai] Bot上线通知", "您的 Mirai bot [${bot.id}(${bot.nick})] 登录成功!") + } + } + // 订阅下线事件 + globalEventChannel().subscribeAlways { + if (PluginConfig.logoutNotify) { + sendMail("[Mirai] Bot离线通知", "您的 Mirai bot [${bot.id}(${bot.nick})] 下线了!\n" + + "触发事件:$this") + } + } + } + + override fun onDisable() { + if (!PluginConfig.disableNotify) + return + sendMail("[Mirai] 控制台关闭通知", "J Mail Notify 插件已关闭") + } + + /** + * 发送邮件 + * @param title 邮件标题 + * @param message 邮件内容 + * @return 是否发送完成 + */ + fun sendMail(title: String, message: String): Boolean { + logger.info("正在尝试向 ${PluginConfig.sendToEMail} 发送邮件 \"$title | $message\"") + if (PluginConfig.smtpEMail.isEmpty() + || PluginConfig.smtpPassword.isEmpty() + || PluginConfig.smtpHost.isEmpty() + || PluginConfig.sendToEMail.isEmpty()) { + logger.warning("邮箱参数未设置,无法发送邮件。请先设置发件人与收件人的邮箱。QQ邮箱帮助: https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256") + return false + } + + try { + val props = Properties() + props["mail.smtp.host"] = PluginConfig.smtpHost + props["mail.smtp.port"] = PluginConfig.smtpPort.toString() + props["mail.smtp.auth"] = "true" + props["mail.smtp.ssl.enable"] = if (PluginConfig.useSSL) "true" else "false" + val session = Session.getDefaultInstance(props, object : Authenticator() { + override fun getPasswordAuthentication(): PasswordAuthentication { + return PasswordAuthentication(PluginConfig.smtpEMail, PluginConfig.smtpPassword) + } + }) +// session.debug = true + + val mimeMessage = MimeMessage(session) + mimeMessage.setFrom(InternetAddress(PluginConfig.smtpEMail)) + mimeMessage.setRecipients( + jakarta.mail.Message.RecipientType.TO, InternetAddress.parse(PluginConfig.sendToEMail, false)) + mimeMessage.setText(message) + mimeMessage.subject = title + mimeMessage.sentDate = Date() + + session.getTransport("smtp").use { + it.connect() + it.sendMessage(mimeMessage, mimeMessage.allRecipients) + } + logger.info("邮件发送成功 \"$title\"") + return true + } catch (e: Throwable) { + logger.error("发送邮件时发生异常", e) + return false + } } } \ No newline at end of file diff --git a/src/main/kotlin/PluginCommands.kt b/src/main/kotlin/PluginCommands.kt index 1db031b..ea4f1ab 100644 --- a/src/main/kotlin/PluginCommands.kt +++ b/src/main/kotlin/PluginCommands.kt @@ -1,4 +1,82 @@ package top.jie65535.mirai.mailnotify -class PluginCommand { +import net.mamoe.mirai.console.command.CommandSender +import net.mamoe.mirai.console.command.CompositeCommand + +object PluginCommands : CompositeCommand(JMailNotify, "jmn", + description = "邮件通知命令") { + + @SubCommand + @Description("设置SMTP发件人邮箱") + suspend fun CommandSender.setSender(email: String, smtpPassword: String) { + if (email.isEmpty() || smtpPassword.isEmpty()) { + sendMessage("参数不能为空") + } else { + PluginConfig.smtpEMail = email + PluginConfig.smtpPassword = smtpPassword + sendMessage("OK") + } + } + + @SubCommand + @Description("设置SMTP服务器") + suspend fun CommandSender.setSmtpServer(host: String, port: Int) { + if (host.isEmpty() || port == 0) { + sendMessage("参数不能为空") + } else { + PluginConfig.smtpHost = host + PluginConfig.smtpPort = port + sendMessage("OK") + } + } + + @SubCommand + @Description("设置收件人邮箱地址") + suspend fun CommandSender.setSendTo(email: String) { + if (email.isEmpty()) { + sendMessage("参数不能为空") + } else { + PluginConfig.sendToEMail = email + sendMessage("OK") + } + } + + @SubCommand + @Description("发送测试邮件") + suspend fun CommandSender.test( + title: String = "[Mirai] 测试邮件", message: String = "这是一封测试邮件,若您收到这封邮件,说明当前插件参数配置正确。") { + if (JMailNotify.sendMail(title, message)) { + sendMessage("邮件已发送") + } else { + sendMessage("邮件发送失败,具体错误信息请查看控制台日志") + } + } + + @SubCommand + @Description("重载配置") + suspend fun CommandSender.reload() { + reload() + sendMessage("OK") + } + + @SubCommand + @Description("设置登录通知") + suspend fun CommandSender.setLogin(isEnabled: Boolean) { + PluginConfig.loginNotify = isEnabled + sendMessage("OK") + } + + @SubCommand + @Description("设置登出通知") + suspend fun CommandSender.setLogout(isEnabled: Boolean) { + PluginConfig.logoutNotify = isEnabled + sendMessage("OK") + } + + @SubCommand + @Description("设置关闭通知") + suspend fun CommandSender.setDisabled(isEnabled: Boolean) { + PluginConfig.disableNotify = isEnabled + sendMessage("OK") + } } \ No newline at end of file diff --git a/src/main/kotlin/PluginConfig.kt b/src/main/kotlin/PluginConfig.kt index b7943f6..58df489 100644 --- a/src/main/kotlin/PluginConfig.kt +++ b/src/main/kotlin/PluginConfig.kt @@ -1,4 +1,65 @@ -package top.jie65535.mirai +package top.jie65535.mirai.mailnotify -class PluginConfig { +import net.mamoe.mirai.console.data.AutoSavePluginConfig +import net.mamoe.mirai.console.data.ValueDescription +import net.mamoe.mirai.console.data.value + +/** + * 插件配置 + */ +object PluginConfig : AutoSavePluginConfig("config") { + + /** + * SMTP地址 + */ + @ValueDescription("SMTP地址( QQ邮箱是 smtp.qq.com )") + var smtpHost: String by value("smtp.qq.com") + + /** + * SMTP端口 + */ + @ValueDescription("SMTP端口号( QQ邮箱默认 465 )") + var smtpPort: Int by value(465) + + /** + * 是否使用SSL + */ + @ValueDescription("是否使用SSL( QQ邮箱默认 是 )") + val useSSL: Boolean by value(true) + + /** + * SMTP邮箱(发件人) + */ + @ValueDescription("SMTP邮箱(发件人)") + var smtpEMail: String by value() + + /** + * SMTP授权码 + */ + @ValueDescription("SMTP授权码") + var smtpPassword: String by value() + + /** + * 收件人邮箱 + */ + @ValueDescription("收件人邮箱") + var sendToEMail: String by value() + + /** + * 机器人登录时通知 + */ + @ValueDescription("机器人登录时通知") + var loginNotify: Boolean by value(true) + + /** + * 机器人登出时通知 + */ + @ValueDescription("机器人登出时通知") + var logoutNotify: Boolean by value(true) + + /** + * 插件关闭时通知 + */ + @ValueDescription("插件关闭时通知") + var disableNotify: Boolean by value(true) } \ No newline at end of file diff --git a/src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin b/src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin index 518adf8..affbdbe 100644 --- a/src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin +++ b/src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin @@ -1 +1 @@ -top.jie65535.mirai.JMailNotify \ No newline at end of file +top.jie65535.mirai.mailnotify.JMailNotify \ No newline at end of file diff --git a/src/test/kotlin/SendMailTest.kt b/src/test/kotlin/SendMailTest.kt index 53a868d..d51ec6a 100644 --- a/src/test/kotlin/SendMailTest.kt +++ b/src/test/kotlin/SendMailTest.kt @@ -1,2 +1,13 @@ -class SendMailTest { +import net.mamoe.mirai.console.MiraiConsole +import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable +import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.load +import net.mamoe.mirai.console.terminal.MiraiConsoleTerminalLoader +import top.jie65535.mirai.mailnotify.JMailNotify + +@net.mamoe.mirai.console.util.ConsoleExperimentalApi +suspend fun main() { + MiraiConsoleTerminalLoader.startAsDaemon() + JMailNotify.load() + JMailNotify.enable() + MiraiConsole.job.join() } \ No newline at end of file