电子邮件 是最早的互联网应用之一。
一个 电子邮件系统 至少由三部分组成
一封 电子邮件 由两个部分组成
一个 电子邮件地址 由三个部分组成
1*( atext / "." ) "@" ldh-str 1*( "." ldh-str )
/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
总结一下就是 三种协议,一种格式
sendmail
busybox 中的 sendmail
-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
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
powershell
Send-MailMessage
Send-MailMessage 不支持 465 端口的 smtps ,如果要使用 smtps 就要改用其他端口
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.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.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。以下是一些常用的方法:
-eq 运算符你可以直接将变量与 $null 进行比较:
if ($variable -eq $null) {
Write-Host "变量是 null"
} else {
Write-Host "变量不是 null"
}
-ne 运算符如果你想检查变量是否不为 null,可以使用 -ne 运算符:
if ($variable -ne $null) {
Write-Host "变量不是 null"
} else {
Write-Host "变量是 null"
}
if 语句你还可以使用简单的 if 语句来检查变量的存在性:
if ($variable) {
Write-Host "变量不是 null 或空"
} else {
Write-Host "变量是 null 或空"
}
IsNullOrEmpty 方法如果你想同时检查变量是否为 null 或空字符串,可以使用 IsNullOrEmpty 方法:
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
https://github.com/pear/Mail 2.0
$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);
https://github.com/PHPMailer/PHPMailer 6.9
//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}";
}
https://github.com/symfony/mailer 6.4
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);
https://github.com/zetacomponents/Mail 1.9
安装命令
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 的命令 -->