v0.0.1初版
This commit is contained in:
parent
285ee22ca0
commit
345b0002d4
25
.gitignore
vendored
25
.gitignore
vendored
@ -1,23 +1,2 @@
|
||||
# ---> Go
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# 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
|
||||
|
||||
/target
|
||||
/.idea
|
||||
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal 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
1391
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal 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
149
src/main.rs
Normal 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)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user