电子邮件 是最早的互联网应用之一。
一个 电子邮件系统 至少由三部分组成
一封 电子邮件 由两个部分组成
一个 电子邮件地址 由三个部分组成
1*( atext / "." ) "@" ldh-str 1*( "." ldh-str )
/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
总结一下就是 三种协议,一种格式
<!-- ### 客户端 ### 服务端 ## 三种协议,一种格式 ### SMTP ### IMAP ### POP3 ### Internet Message Format -->
<!-- SMTPS 和 STARTTLS 是两种不一样的加密方式 MTA-STS -->
适用于 nc telnet openssl
大致分为五个步骤
echo -n "bootstrap@example.com" | base64
echo -n "SendEmails" | base64
AUTH LOGIN
Ym9vdHN0cmFwQGV4YW1wbGUuY29t
U2VuZEVtYWlscw==
\0printf "\0%s\0%s" "bootstrap@example.com" "SendEmails" | base64
AUTH PLAIN
AGJvb3RzdHJhcEBleGFtcGxlLmNvbQBTZW5kRW1haWxz
\0,字符串要以 auth 开头printf "auth\0%s\0%s" "bootstrap@example.com" "SendEmails" | base64
AUTH PLAIN YXV0aABib290c3RyYXBAZXhhbXBsZS5jb20AU2VuZEVtYWlscw==
一个收件人的例子
HELO example.com
AUTH LOGIN
MAIL FROM:<alice@example.com>
RCPT TO:<bob@example.com>
DATA
Date: Mon, 4 April 2022
From: Alice <alice@example.com>
Subject: Eggs benedict casserole
To: Bob <bob@example.com>
Hi Bob,
I will bring the eggs benedict casserole recipe on Friday.
-Alice
.
QUIT
多个个收件人的例子
HELO example.com
AUTH LOGIN
MAIL FROM:<alice@example.com>
RCPT TO:<bob1@example.com>
RCPT TO:<bob2@example.com>
DATA
Date: Mon, 4 April 2022
From: Alice <alice@example.com>
Subject: Eggs benedict casserole
To: bob1 <bob1@example.com>, bob2 <bob2@example.com>
Hi Bob,
I will bring the eggs benedict casserole recipe on Friday.
-Alice
.
QUIT
HELO example.com
AUTH LOGIN
MAIL FROM:<alice@example.com>
RCPT TO:<bob1@example.com>
RCPT TO:<bob2@example.com>
DATA
Date: Mon, 4 April 2022
From: Alice <alice@example.com>
Subject: Eggs benedict casserole
To: bob1 <bob1@example.com>
Cc: bob2 <bob2@example.com>
Hi Bob,
I will bring the eggs benedict casserole recipe on Friday.
-Alice
.
QUIT
smtp 命令 NOOP HELP RSET
<!-- 可以用 mailpit 作为测试用的服务器 感觉这个位置应该需要一些截图 还需要继续总结一下有哪些 rfc -->
-S 表示SMTP服务器的地址和端口号-au 表示发送邮箱名-ap 表示发送邮箱授权码sendmail -f from@xx.com -t to@xx.com -S smtp.qq.com:465 -auxxx -apxxxx -s mail.txt
cat mail.txt | sendmail -f from@xx.com -t to@xx.com -S smtp.qq.com:465 -auxxx -apxxxx
cat <<- EOF | sendmail -f from@xx.com -t to@xx.com -S smtp.qq.com:465 -auxxx -apxxxx
Date: Fri, 5 Apr 2024 06:27:52 +0000
To: bob1@example.com, bob2@example.com, bob3@example.com
From: Mailer <alice@example.com>
Subject: Here is the subject
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
This is the test message
EOF
curl -v --ssl --url 'smtps://smtp.qq.com:465/smtp.qq.com' \
--user 'alice@example.com:NvbQBTZW5kRW' \
--mail-from 'alice@example.com' \
--mail-rcpt 'bob@example.com' \
--login-options AUTH=LOGIN \
--upload-file mail-curl.txt
cat mail-curl.txt | curl -v --ssl --url 'smtps://smtp.qq.com:465/smtp.qq.com' \
--user 'alice@example.com:NvbQBTZW5kRW' \
--mail-from 'alice@example.com' \
--mail-rcpt 'bob@example.com' \
--login-options AUTH=LOGIN \
--upload-file -
cat <<- EOF | curl -v --no-progress-meter --url 'smtp://127.0.0.1:25/NB4045' \
--user 'alice@example.com:NvbQBTZW5kRW' \
--mail-from 'alice@example.com' \
--mail-rcpt 'bob1@example.com' \
--mail-rcpt 'bob2@example.com' \
--mail-rcpt 'bob3@example.com' \
--login-options AUTH=LOGIN \
--upload-file - \
Date: Fri, 5 Apr 2024 06:27:52 +0000
To: bob1@example.com, bob2@example.com, bob3@example.com
From: Mailer <alice@example.com>
Subject: Here is the subject
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
This is the test message
EOF
<!-- curl 用的是第一种方式,所以当前版本的 curl 无法发送邮件到 smtp.qq.com 加上这个参数 --sasl-ir 1 就能使账号密码放在同一行里了 但加上这个参数后,还会再请求一次,而且还是请求失败的那种,可能是我不了解 sasl curl -v --ssl --url 'smtps://smtp.qq.com:465/smtp.qq.com' \ --user 'alice@example.com:NvbQBTZW5kRW' \ --mail-from 'alice@example.com' \ --mail-rcpt 'bob@example.com' \ --sasl-ir 1 \ --upload-file mail-curl.txt -->
Send-MailMessage -SmtpServer "smtp.qq.com" -Port 587 -UseSsl `
-Credential $(New-Object System.Management.Automation.PSCredential("alice@example.com", $(ConvertTo-SecureString "NvbQBTZW5kRW" -AsPlainText -Force))) `
-From "alice@example.com" `
-To 'User02 <user02@fabrikam.com>', 'User03 <user03@fabrikam.com>' `
-Subject 'Test mail' `
-Body "message"
Send-MailMessage -SmtpServer "127.0.0.1" -Port 587 -UseSsl `
-Credential $(New-Object System.Management.Automation.PSCredential("alice@example.com", $(ConvertTo-SecureString "NvbQBTZW5kRW" -AsPlainText -Force))) `
-From "alice@example.com" `
-To 'User02 <user02@fabrikam.com>', 'User03 <user03@fabrikam.com>' `
-Cc 'Cc02 <Cc02@fabrikam.com>', 'Cc03 <Cc03@fabrikam.com>' `
-Bcc 'Bcc02 <Bcc02@fabrikam.com>', 'Bcc03 <Bcc03@fabrikam.com>' `
-Subject '中文Test mail' `
-Encoding 'utf8' `
-Attachments './v2.php' `
-BodyAsHtml `
-Body "<p>中文mailMessage</p>"
$smtpClient = New-Object System.Net.Mail.SmtpClient("smtp.qq.com", 587)
$smtpClient.EnableSsl = $True
$smtpClient.Credentials = New-Object System.Net.NetworkCredential("alice@qq.com", "NvbQBTZW5kRW")
$smtpClient.Send("alice@qq.com", "user02@fabrikam.com", "Subject", "mailMessage")
<!-- ``` $smtpClient = New-Object System.Net.Mail.SmtpClient("127.0.0.1", 25) $smtpClient.Credentials = New-Object System.Net.NetworkCredential("12345678@qq.com", "wdgwshjofvvmdeef") $mailMessage = New-Object System.Net.Mail.MailMessage $mailMessage.From = New-Object System.Net.Mail.MailAddress("jane@contoso.com", "Jane Clayton") $mailMessage.To.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso2.com", "Jane Clayton2"))) $mailMessage.To.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso3.com", "Jane Clayton3"))) $mailMessage.CC.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso4.com", "Jane Clayton4"))) $mailMessage.CC.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso5.com", "Jane Clayton5"))) $mailMessage.Bcc.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso6.com", "Jane Clayton6"))) $mailMessage.Bcc.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso7.com", "Jane Clayton7"))) $contentType = New-Object System.Net.Mime.ContentType $contentType.Name = 'v2.php' $contentType.MediaType = [System.Net.Mime.MediaTypeNames]::Text::Plain System.Net.Mail.Attachment('./v2.php', $contentType) [System.Net.Mime.MediaTypeNames]::Text::Plain System.Net.Mime.MediaTypeNames.Text.Plain [System.Net.Mime.MediaTypeNames.Text]::Plain [System.Net.Mime.MediaTypeNames].ToString() [System.Net.Mime.MediaTypeNames].Text Get-Member -MemberType Property [System.Net.Mime.MediaTypeNames] | Get-Member [System.Net.Mime.MediaTypeNames].Attributes [System.Net.Mime.MediaTypeNames].GetEnumNames 如果是完整的类名,静态类,对象,或者已经赋值的变量 [System.Net.Mail.MailAddress] | Get-Member [System.Net.Mime.MediaTypeNames] | Get-Member $a | Get-Member [System.Net.Mime.MediaTypeNames] | Get-Member $a | Get-Member [AppDomain]::CurrentDomain.GetAssemblies() | ? {$_.Location -and ($_.Location.Split('\')[-1] -eq 'System.Net.Mime.MediaTypeNames.dll')} [System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object { $_.GetTypes() } [System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object { $_.GetTypes() } | Select-Object -First 1 | format-list [System.AppDomain]::CurrentDomain.GetAssemblies() | Select-Object -First 1 | format-list [System.AppDomain]::CurrentDomain.GetAssemblies() | Select-Object -First 1 | Get-Member ([System.AppDomain]::CurrentDomain.GetAssemblies() | Select-Object -First 1 ).GetName() ([System.AppDomain]::CurrentDomain.GetAssemblies() | Select-Object -First 1 ).GetTypes() [System.AppDomain]::CurrentDomain.GetExecutingAssembly() [System.Reflection.Assembly]::GetExecutingAssembly() [System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object { $_.GetTypes() } | Select-Object -First 1 | Get-Member -Name Name Where-Object { $_.GetName() -eq "System" } | Get-Member [System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object { $_.GetTypes() } | ForEach-Object { $_.GetMethods(‘NonPublic, Public, Static’) } | ForEach-Object { $MethodInfo = $_; $_.GetCustomAttributes($false) } | Where-Object { $MethodInfo.Name.ToLower() -eq $FunctionName.ToLower() -and $_.Value -eq $Module } | ForEach-Object { $MethodInfo } 这一段是可行的 只能用在 windows powershell $mscorlib = [AppDomain]::CurrentDomain.GetAssemblies() | ? {$_.Location -and ($_.Location.Split('\')[-1] -eq 'System.dll')} $Win32Native = $mscorlib.GetType('Microsoft.Win32.NativeMethods') $OpenProcessMethod = $Win32Native.GetMethod('OpenProcess', ([Reflection.BindingFlags] 'NonPublic, Public, Static')) $OpenProcessMethod.Invoke($null, @(0x1F0FFF, $False, 524)) 这一段是可行的 只能用在 powershell $mscorlib = [AppDomain]::CurrentDomain.GetAssemblies() | ? {$_.Location -and ($_.Location.Split('\')[-1] -eq 'System.Diagnostics.Process.dll')} $Win32Native = $mscorlib.GetType('Interop+Kernel32') $OpenProcessMethod = $Win32Native.GetMethod('OpenProcess', ([Reflection.BindingFlags] 'NonPublic, Public, Static')) $OpenProcessMethod.Invoke($null, @(0x1F0FFF, $False, 524)) $mscorlib = [AppDomain]::CurrentDomain.GetAssemblies() | ? {$_.Location -and ($_.Location.Split('\')[-1] -eq 'System.dll')} | Select-Object -ExpandProperty Namespace -Unique $mailMessage.SubjectEncoding = [System.Text.Encoding]::UTF8 $mailMessage.BodyEncoding = [System.Text.Encoding]::UTF8 $mailMessage.Subject = "中文Subject" $mailMessage.IsBodyHtml = $True $mailMessage.Body = "<p>中文mailMessage</p>" ``` - System.Web.Mail printf "auth\0%s\0%s" "12345678@qq.com" "wdgwshjofvvmdeef" | base64 $smtpMail = New-Object System.Web.Mail.SmtpMail Add-Type -AssemblyName "System.Web" [System.Web.Mail.SmtpMail] Add-Type -AssemblyName "System.Web" 为什么要单独加载 System.Web 程序集? 因为 powershell 没有默认加载 System.Web 什么是程序集? 就是 .NET 的 .dll 文件 程序集采用可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式,是 .NET 应用程序的构建基块 。 它们向公共语言运行时提供了注意类型实现代码所需的信息。 动态链接会按一定的顺序去搜索 https://learn.microsoft.com/zh-cn/windows/win32/dlls/dynamic-link-library-search-order Add-Type 也可以直接指定 dll 的路径 Add-Type -Path "C:\path\to\your\MyLibrary.dll" $smtpClient = New-Object System.Net.Mail.SmtpClient("127.0.0.1", 25) Get-Help Add-Type $smtpClient = New-Object System.Net.Mail.SmtpClient("smtp.qq.com", 587) $smtpClient.EnableSsl = $True $smtpClient = New-Object System.Net.Mail.SmtpClient("127.0.0.1", 25) $smtpClient.Credentials = New-Object System.Net.NetworkCredential("12345678@qq.com", "wdgwshjofvvmdeef") $mailMessage = New-Object System.Net.Mail.MailMessage $mailMessage.From = New-Object System.Net.Mail.MailAddress("jane@contoso.com", "Jane Clayton") $mailMessage.To.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso2.com", "Jane Clayton2"))) $mailMessage.To.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso3.com", "Jane Clayton3"))) $mailMessage.CC.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso4.com", "Jane Clayton4"))) $mailMessage.CC.Add($(New-Object System.Net.Mail.MailAddress("jane@contoso5.com", "Jane Clayton5"))) $mailMessage.SubjectEncoding = [System.Text.Encoding]::UTF8 $mailMessage.BodyEncoding = [System.Text.Encoding]::UTF8 $mailMessage.Subject = "中文Subject" $mailMessage.IsBodyHtml = $True $mailMessage.Body = "<p>中文mailMessage</p>" $winDir = New-Object -TypeName "System.Text.Encoding" New-Object System.Text.Encoding $smtpClient.Send($mailMessage); IsBodyHtml $smtpClient.Send("12345678@qq.com", "87654321@qq.com", "Subject", "mailMessage"); .NET 中的程序集就是 exe 或 dll 程序集通常有一个或多个命名空间 程序集需要先加载再使用 通常会默认加载一部分程序集 jsc csc vbc windows powershell 依赖 .NET Framework 所以系统里一定有 .NET Framework 有 .NET Framework 也会有 csc jsc vbc 这三个编译器 powershell core 之后有自包含 .NET Framework 的安装包,所以 powershell 可以不依赖 .NET Framework PowerShell 中只要变量不为 null ,就可以用 Get-Member 方法 在 PowerShell 中,可以通过几种方法判断一个变量是否为 `null`。以下是一些常用的方法: ### 1. 使用 `-eq` 运算符 你可以直接将变量与 `$null` 进行比较: ```powershell if ($variable -eq $null) { Write-Host "变量是 null" } else { Write-Host "变量不是 null" } ``` ### 2. 使用 `-ne` 运算符 如果你想检查变量是否不为 `null`,可以使用 `-ne` 运算符: ```powershell if ($variable -ne $null) { Write-Host "变量不是 null" } else { Write-Host "变量是 null" } ``` ### 3. 简单的 `if` 语句 你还可以使用简单的 `if` 语句来检查变量的存在性: ```powershell if ($variable) { Write-Host "变量不是 null 或空" } else { Write-Host "变量是 null 或空" } ``` ### 4. 使用 `IsNullOrEmpty` 方法 如果你想同时检查变量是否为 `null` 或空字符串,可以使用 `IsNullOrEmpty` 方法: ```powershell if ([string]::IsNullOrEmpty($variable)) { Write-Host "变量是 null 或空字符串" } else { Write-Host "变量不是 null 且不是空字符串" } ``` ### 总结 这些方法可以帮助你有效地判断 PowerShell 中的变量是否为 `null`。选择适合你需求的方法即可。如果你有其他问题或需要进一步的帮助,请告诉我! -->
[mail function]
; For Win32 only.
; https://php.net/smtp
SMTP = localhost
; https://php.net/smtp-port
smtp_port = 25
;sendmail_from = me@example.com
// 设置收件人地址
$to = 'asd <asd@123.com>, asd2 <asd2@123.com>';
// 设置邮件主题
$subject = 'subject';
// 设置邮件正文
$message = '<p>message</p>';
// 设置邮件头部信息,包括发件人地址和回复地址
$headers = [
'From' => 'Mailer <12345678@qq.com>',
'Content-Type' => 'text/html; charset=utf-8',
'Reply-To' => 'bing@example.com',
];
$additional_params = '';
// 调用 mail 函数发送邮件
if (mail($to, $subject, $message, $headers, $additional_params)) {
echo "邮件发送成功";
} else {
echo "邮件发送失败";
}
// 理论上是可以在 message 里塞附件的,
// 一些版本的 sendmail 可以在命令行里设置 smtp 地址和账号密码,这时就可以通过 additional_params 变量设置
// mail 函数里的 additional_params 参数可以设置 mta 的更多的命令行参数,
// 其实就类似于这样
// echo "邮件正文" | sendmail -t -i additional_params
// 假设 sendmail 支持 -S -au -ap 三个参数,那么 $additional_params 可以设置成
// $additional_params = ' -S smtp.qq.com:465 -auxxx -apxxxx';
// 那么最后的命令类似于
// echo "邮件正文" | sendmail -t -i -S smtp.qq.com:465 -auxxx -apxxxx
$params = [
'host' => 'smtp.qq.com',
'port' => '465',
'auth' => true,
'username' => '123456@qq.com',
'password' => '',
'starttls' => true,
];
$smtp = Mail::factory('smtp', $params);
$recipients = [
'to1@address.com',
'to2@address.com',
'cc@address.com',
'bcc@address.com',
]; // 包含 to cc bcc 的收件地址
$headers = [
'Date' => '',
'To' => '',
'From' => '',
'Subject' => '',
'MIME-Version' => '',
'Content-Type' => 'text/html; charset=utf-8',
];
$body = '<p>message</p>';
$smtp->send($recipients, $headers, $body);
//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require 'vendor/autoload.php';
//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = 'smtp.qq.com'; //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = 'joe@example.net'; //SMTP username
$mail->Password = 'matthew'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
//Recipients
$mail->setFrom('joe@example.net', 'Mailer');
// $mail->addAddress('joe@example.net', 'Joe User'); //Add a recipient
$mail->addAddress('info@example.com'); //Name is optional
// $mail->addReplyTo('info@example.com', 'Information');
// $mail->addCC('cc@example.com');
// $mail->addBCC('bcc@example.com');
//Attachments
// $mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
require './vendor/autoload.php';
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;
$transport = Transport::fromDsn('smtp://localhost');
$mailer = new Mailer($transport);
$email = (new Email())
->from('hello@example.com')
->to('you@example.com')
//->cc('cc@example.com')
//->bcc('bcc@example.com')
//->replyTo('fabien@example.com')
//->priority(Email::PRIORITY_HIGH)
->subject('Time for Symfony Mailer!')
->text('Sending emails is fun again!')
->html('<p>See Twig integration for better HTML integration!</p>');
$mailer->send($email);
require './vendor/autoload.php';
use Laminas\Mail\Message;
$message = new Message();
$message->addFrom('matthew@example.org', 'Matthew Somelli');
$message->addTo('foobar@example.com', 'foobar');
$message->addTo('foobar2@example.com', 'foobar2');
$message->addCc('ralph@example.org', 'ralph');
$message->addCc('ralph2@example.org', 'ralph2');
$message->addBcc('enrico@example.org', 'enrico');
$message->addBcc('enrico2@example.org', 'enrico2');
$message->addReplyTo('matthew@example.com', 'Matthew');
$message->setSender('matthew@example.org', 'Matthew Sommeli');
$message->setSubject('Sending an email from Laminas\Mail!');
// $message->setEncoding('UTF-8');
$message->setBody('This is the message body.');
// echo $message->toString(); // 这样可以生成一个 IMF 字符串,
$transport = new \Laminas\Mail\Transport\Smtp();
$options = new \Laminas\Mail\Transport\SmtpOptions([
'name' => 'localhost',
'host' => '127.0.0.1',
// 'connection_class' => 'login',
'connection_class' => 'plain',
'connection_config' => [
'username' => 'user',
'password' => 'pass',
],
]);
$transport->setOptions($options);
$transport->send($message);
安装命令
composer require zetacomponents/mail
这个库和其它的不一样,没有命名空间
require __DIR__ . '/vendor/autoload.php';
// 配置参数(根据实际情况修改)
$smtpHost = 'localhost'; // SMTP服务器地址
$smtpPort = 25; // 端口
$smtpUsername = 'user@example.com'; // 发件邮箱
$smtpPassword = 'your-password'; // 邮箱密码或应用专用密码
$fromEmail = 'sender@example.com'; // 发件人地址
$fromName = '系统发件人'; // 发件人名称
$toEmail = 'recipient@example.com';// 收件人地址
$toName = '收件人名称'; // 收件人名称
// 创建邮件对象
$mail = new ezcMail();
$mail->from = new ezcMailAddress($fromEmail, $fromName);
$mail->addTo(new ezcMailAddress($toEmail, $toName));
$mail->subject = '来自 Composer 示例的测试邮件';
// 发送纯文本
// $mail->body = new ezcMailText("这是一封通过 zetacomponents/mail 和 Composer 发送的邮件。", 'utf-8');
// 发送html
$textPart = new ezcMailText("<h1>这是一封通过 zetacomponents/mail 和 Composer 发送的邮件。</h1>", 'utf-8');
$textPart->subType = 'html';
$mail->body = $textPart;
// 配置 SMTP 传输
$options = new ezcMailSmtpTransportOptions();
// $options->connectionType = ezcMailSmtpTransport::CONNECTION_TLS; // 使用 TLS 加密
$transport = new ezcMailSmtpTransport(
$smtpHost,
$smtpUsername,
$smtpPassword,
$smtpPort,
$options
);
// 发送邮件
try {
$transport->send($mail);
echo "邮件已成功发送至 {$toEmail}";
} catch (Exception $e) {
echo "发送失败: " . $e->getMessage();
}
<!-- ## python 发送邮件 https://docs.python.org/zh-cn/3.13/library/smtplib.html https://docs.python.org/zh-cn/3.13/library/email.html https://docs.python.org/zh-cn/3.13/library/email.examples.html -->
roundcube-framework-1.6.10.tar.gz roundcubemail-1.6.10-complete.tar.gz roundcubemail-1.6.10.tar.gz
<!-- docker run --name emailsystem --rm -it -p 8080:8080 php:8.1-bullseye /bin/bash cp /etc/apt/sources.list /etc/apt/sources.list_bak && \ sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \ apt update && \ apt install -y vim && \ apt install -y curl && \ apt install -y net-tools && \ apt install -y netcat && \ apt install -y procps && \ apt install -y dnsutils && \ apt install -y mailutils && \ apt install -y postfix && \ apt install -y bzip2 && \ apt install -y make && \ apt install -y gcc && \ apt install -y git && \ cd && \ curl -O "https://busybox.net/downloads/busybox-1.36.1.tar.bz2" && \ tar -xjf ./busybox-1.36.1.tar.bz2 && \ cd busybox-1.36.1 && \ make defconfig && \ make install && \ cp /root/busybox-1.36.1/busybox /bin/busybox && \ cd curl -sS -o composer.phar https://getcomposer.org/composer.phar && \ chmod 0755 composer.phar && \ mv composer.phar /usr/local/bin/composer cp /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini apt install -y libzip-dev unzip && \ docker-php-ext-install zip apt install -y libicu-dev && \ docker-php-ext-install intl docker-php-ext-install exif apt install -y \ libfreetype6-dev \ libjpeg62-turbo-dev \ libjpeg-dev \ libpng-dev \ libwebp-dev && \ docker-php-ext-configure gd --with-jpeg --with-freetype && \ docker-php-ext-install gd docker-php-ext-install opcache curl -L -o roundcubemail.tar.gz --connect-timeout 120 --max-time 3600 --retry 100 --retry-delay 5 https://github.com/roundcube/roundcubemail/releases/download/1.6.10/roundcubemail-1.6.10-complete.tar.gz tar -zxf roundcubemail.tar.gz cd roundcubemail-1.6.10 cp composer.json composer.json-bak cp composer.json-dist composer.json composer update PHP_CLI_SERVER_WORKERS="10" php -S 127.0.0.1:8080 PHP_CLI_SERVER_WORKERS="10" php -S 0.0.0.0:8080 https://8080-cs-285386365050-default.cs-asia-east1-jnrc.cloudshell.dev/installer/index.php touch roundcubemail.sqlite cat config/config.inc.php vi config/config.inc.php sqlite:///roundcubemail.sqlite chmod 777 roundcubemail.sqlite -->
<!-- 电子邮件 名词 email e-mail Electronic Mail 电子的 邮件 电子邮件 电邮 组成 mta mua mda 主流的操作系统都有预装邮件客户端(mua) Microsoft Mail 更早的,从dos时代开始 Windows Messaging 95 , win95里的 ie3.0 也可以作为mua,这个mua后续发展出 Outlook Express Outlook Express 98-xp Windows Live Mail vista-7 Windows Mail 8-11 Outlook For Windows 10-11 unix/linux 里的 mailx iOS 安卓 winphone 塞班 S40 都有预装邮件客户端,就像浏览器一样是一个重要的系统组件 如何搭建一个邮件服务器 单机的在不同用户间发送邮件 apt install -y mailutils 这句命令安装的是 exim 如无意外,安装完后就能直接用 sendmail mail mailx 命令了 mail 和 mailx 链接到 mail.mailutils sendmail 链接到 exim4 增加一个用户 useradd -m user1 发送邮件给其它用户 使用 mailx 命令发送 echo "test mail content" | mailx -s "test mail subject" root echo 邮件内容 | mailx -s 邮件主题 用户名 使用 sendmail 命令发送 echo -e "From: root\nTo: root\nSubject: 问候\n\n我是 root 用户,这是一封用 sendmail 命令发送的邮件。" | sendmail -t sendmail -t <<EOF From: root To: root Subject: 问候 我是 root 用户,这是一封用 sendmail 命令发送的邮件。 EOF; 查看用户的邮件 mail -u root mail -u 用户名 mail -f /var/spool/mail/mail mail -f /var/mail/mail root用户要用这种方式才能查看接收的邮件 mail -f 用于保存邮件的文件路径 mail -f /var/mail/user1 邮件保存的位置 目录 /var/spool/mail 这个目录会软连接到 /var/mail /var/mail 这个是实际的目录 文件 /var/mail/root /var/mail/mail /var/mail/用户名 日志 日志文件的目录 /var/log/exim4 日志文件 /var/log/exim4/mainlog 预防万一可以先事先新建一个 ls -l /var/log/exim4 mkdir -p /var/log/exim4 touch /var/log/exim4/mainlog chmod 777 /var/log/exim4/mainlog 查看日志 cat /var/log/exim4/mainlog 在局域网里自娱自乐 至少需要搭建 smtp 和 imap 至少要开启这两个端口 smtp(25) imap(143) 最好再加上这两个 smtps(587) imaps(993) 还有这几个 smtps(465) pop3(110) pop3s(995) smtp(2525) 587 才是标准的 smtps 端口 rfc3207 465 比 587 更早出现 465 是一开连接就启用 tls 465 很长一段时间都不是标准,直到 rfc8314 587 是连接完成后再通过 STARTTLS命令 启用 tls 除了 smtps 之外,还有不少的协议使用这种明文命令的形式启用 tls 这种 tls 被称为 机会型TLS(Opportunistic TLS) 有些电子邮件服务通过端口 2525 提供 SMTP 传输。但它并不是电子邮件的标准端口 假设已经安装好 exim 修改配置文件 启动 尝试通过ip发送邮件 能收发外网的邮件 除了 搭建 smtp 和 imap 之外,还要做好域名的解释 域名解释才是最困难的部分 域名解释 A 记录 @ 指向 ip CNAME 记录 mail 指向 A 记录 MX 记录 @ 指向 CNAME 记录 TXT 记录 spf dkim dmarc DANE MTA-STS PTR 记录 域名 指向 ip 各种代理 mua webmail RainLoop mta exim Postfix sendmail amavisd-new 调度 ClamAV 和 SpamAssassin ClamAV 邮件反病毒 SpamAssassin 过滤垃圾邮件 mda Dovecot msa mra maa opendkim 还有更多? bimi RUA RUF MTA-STS TLS-RPT 要确保这几个端口的开放 25 465 143 993 除了安全组,防火墙,还要向运营商确认这几个端口有没有开放 mta Mail Transfer Agent(邮件传输代理) 这个是邮件系统的核心 主要用于 接收邮件 把邮件转发给其它mta 把邮件转发给mda或保存在本地 常见的 mta 有三种 sendmail 最古老的 mta 之一 可以通过命令行发送邮件 可以作为 smtp 服务器运行 postfix Postfix 是为了替代 Sendmail 而设计的,提供了更现代化的特性和更高的安全性 兼容一部分 sendmail 的命令 exim4 兼容一部分 sendmail 的命令 date --rfc-2822 RFC 2487 SMTP Service Extension for Secure SMTP over TLS RFC 3207 SMTP Service Extension for Secure SMTP over Transport Layer Security -->