v0.0.1初版
This commit is contained in:
parent
285ee22ca0
commit
345b0002d4
25
.gitignore
vendored
25
.gitignore
vendored
@ -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
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