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
+邮件已发送
+```
+
\ 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