v0.0.1初版

This commit is contained in:
taynpg 2024-07-23 13:29:05 +08:00
parent 285ee22ca0
commit 345b0002d4
5 changed files with 1561 additions and 23 deletions

25
.gitignore vendored
View File

@ -1,23 +1,2 @@
# ---> Go /target
# If you prefer the allow list template instead of the deny list, see community template: /.idea
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work

10
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"files.autoSave": "onFocusChange",
"editor.fontFamily": "Consolas, 'Courier New', monospace",
"editor.fontSize": 16,
"rust-analyzer.inlayHints.parameterHints.enable": false,
"rust-analyzer.inlayHints.typeHints.enable": false,
"rust-analyzer.debug.engineSettings": {
"args": ["D:/333333333333333333", "15890635691typ"]
}
}

1391
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "mail-send"
version = "0.1.0"
edition = "2021"
[dependencies]
lettre = "0.11.7"
zip = "2.1.5"
walkdir = "2.5.0"

149
src/main.rs Normal file
View File

@ -0,0 +1,149 @@
use lettre::message::{Attachment, Mailbox, Message, MultiPart, SinglePart};
use lettre::{SmtpTransport, Transport};
use std::env;
use std::fs::{self, File};
use std::io::{Read, Result, Write};
use std::path::Path;
use walkdir::WalkDir;
use zip::write::SimpleFileOptions;
use zip::ZipWriter;
const SUBJECT_CONTENT: &str = "转tangjie收";
const SUBJECT_CONTENT_ZIP: &str = "转tangjie收.zip";
// 邮件发送者和接收者
const SENDER_EMAIL: &str = "taynpg@163.com";
const RECIPIENT_EMAIL: &str = "sinxmiao@163.com";
const SMTP_SERVER: &str = "smtp.163.com";
const SMTP_USERNAME: &str = "taynpg";
// P: AsRef<Path>:这是一个泛型参数,表示 compress_directory 函数可以接受任何实现了 AsRef<Path> trait 的类型
// 作为目录路径。AsRef<Path> 是一个 trait,用于将类型转换为 Path 类型的引用。常见的实现包括 &str 和 String 类型。
fn compress_directory<P: AsRef<Path>>(dir_path: P) -> Result<()> {
let dir_path = dir_path.as_ref();
let zip_path = dir_path.with_file_name(SUBJECT_CONTENT_ZIP);
// Check if the zip file already exists and delete it if so
if zip_path.exists() {
println!("File {:?} already exists. It will be deleted.", zip_path);
fs::remove_file(&zip_path)?;
}
// Create a new zip file
let file = File::create(&zip_path)?;
let mut zip = ZipWriter::new(file);
// Set options for file compression
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o755);
// Walk the directory and add files to the zip
for entry in WalkDir::new(dir_path) {
let entry = entry?;
let path = entry.path();
// Strip the prefix and handle the error explicitly
let name = match path.strip_prefix(dir_path) {
Ok(name) => name,
Err(e) => {
eprintln!("Error stripping prefix: {:?}", e);
continue; // Skip this entry
}
};
if path.is_file() {
// Create a zip file entry and write its content
zip.start_file_from_path(name, options)?;
let mut f = File::open(path)?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?;
zip.write_all(&buffer)?;
} else if path.is_dir() {
// Create a directory entry
if !name.as_os_str().is_empty() {
zip.add_directory_from_path(name, options)?;
}
}
}
zip.finish()?;
println!("Directory compressed to {:?}", zip_path);
Ok(())
}
fn send(file_path: &str, pwd: &str) {
// 创建邮件
let email = Message::builder()
.from(SENDER_EMAIL.parse::<Mailbox>().unwrap())
.to(RECIPIENT_EMAIL.parse::<Mailbox>().unwrap())
.subject(SUBJECT_CONTENT)
.multipart(
MultiPart::mixed()
.singlepart(SinglePart::plain(String::from(SUBJECT_CONTENT)))
.singlepart(Attachment::new(String::from(SUBJECT_CONTENT_ZIP)).body(
read_file(file_path).unwrap(),
"application/zip".parse().unwrap(),
)),
)
.unwrap();
// SMTP 服务器配置
let mailer = SmtpTransport::relay(SMTP_SERVER)
.unwrap()
.credentials((SMTP_USERNAME, pwd).into())
.build();
// 发送邮件
match mailer.send(&email) {
Ok(_) => println!("Email sent successfully!"),
Err(e) => eprintln!("Could not send email: {:?}", e),
}
}
fn main() {
// 获取命令行参数
let args: Vec<String> = env::args().collect();
// 打印所有命令行参数
println!("Command line arguments:");
for arg in &args {
println!("{}", arg);
}
// 处理第一个参数(如果存在)
if args.len() < 2 {
println!("first arg: path, second arg: password");
return;
}
let first_arg = &args[1];
let second_arg = &args[2];
println!("First argument: {}", first_arg);
if let Err(e) = compress_directory(first_arg) {
eprintln!("Error compressing directory: {:?}", e);
}
let parent_path = Path::new(first_arg);
// 获取父目录
if let Some(parent) = parent_path.parent() {
// 创建新的路径,拼接文件名
let new_path = parent.join(SUBJECT_CONTENT_ZIP);
println!("新的路径是: {}", new_path.display());
// 尝试将 Path 转换为 &str
match new_path.to_str() {
Some(path_str) => send(path_str, second_arg), // 调用函数,传递 &str
None => eprintln!("Path contains invalid UTF-8 characters"),
}
} else {
println!("路径没有父目录");
return;
}
}
// 读取文件内容的辅助函数
fn read_file(path: &str) -> Result<Vec<u8>> {
let mut file = File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}