Add matching rust implementation for Go HashMessage.
This commit is contained in:
parent
af87a3cade
commit
7bbdaec84b
117
Cargo.lock
generated
117
Cargo.lock
generated
@ -13,60 +13,112 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.10.1"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "charset"
|
name = "charset"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f426e64df1c3de26cbf44593c6ffff5dbfd43bbf9de0d075058558126b3fc73"
|
checksum = "18e9079d1a12a2cc2bffb5db039c43661836ead4082120d5844f02555aca2d46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "email"
|
name = "email"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mailparse",
|
"mailparse",
|
||||||
"regex",
|
"regex",
|
||||||
|
"sha1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.20"
|
version = "0.8.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9"
|
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mailparse"
|
name = "generic-array"
|
||||||
version = "0.9.2"
|
version = "0.14.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51a60bad00d8aa905d31cf239f207ad4ef16c963ea53cf522d5fd7dc7f3ecfe2"
|
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.139"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mailparse"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b56570f5f8c0047260d1c8b5b331f62eb9c660b9dd4071a8c46f8c7d3f280aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
|
||||||
"charset",
|
"charset",
|
||||||
|
"data-encoding",
|
||||||
"quoted_printable",
|
"quoted_printable",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -78,9 +130,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quoted_printable"
|
name = "quoted_printable"
|
||||||
version = "0.4.1"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86cedf331228892e747bb85beb130b6bb23fc628c40dde9ea01eb6becea3c798"
|
checksum = "a24039f627d8285853cc90dcddf8c1ebfaa91f834566948872b225b9a28ed1b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
@ -98,3 +150,26 @@ name = "regex-syntax"
|
|||||||
version = "0.6.28"
|
version = "0.6.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|||||||
@ -7,5 +7,6 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mailparse = "0.9.2"
|
mailparse = "0.14.0"
|
||||||
regex = "1.7.0"
|
regex = "1.7.0"
|
||||||
|
sha1 = "0.10.5"
|
||||||
|
|||||||
24
hash_test.go
Normal file
24
hash_test.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/mail"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHashReader(t *testing.T) {
|
||||||
|
got, err := HashMessage(&mail.Message{
|
||||||
|
Header: mail.Header{
|
||||||
|
"Subject": []string{"Test"},
|
||||||
|
"From": []string{"me@myself.com"},
|
||||||
|
"To": []string{"you@yourself.com"},
|
||||||
|
},
|
||||||
|
Body: nil,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to parse: %v", err)
|
||||||
|
}
|
||||||
|
want := "1b25d59ed0ade6a762145c58643717477b054fd1"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("HashReader(msg) = %s; want %s", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,6 @@
|
|||||||
use std::env;
|
use std::{env, error::Error, fs::File, io::prelude::*, process::exit, slice::Iter};
|
||||||
use std::error::Error;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::process::exit;
|
|
||||||
use std::slice::Iter;
|
|
||||||
|
|
||||||
use mailparse::dateparse;
|
use mailparse::{dateparse, MailHeaderMap};
|
||||||
use mailparse::MailHeaderMap;
|
|
||||||
|
|
||||||
fn newline(b: &u8) -> bool {
|
fn newline(b: &u8) -> bool {
|
||||||
*b == b'\n'
|
*b == b'\n'
|
||||||
@ -57,15 +51,15 @@ fn parse_mbox(mbox_bytes: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
|||||||
let mail = mailparse::parse_mail(mail_bytes).unwrap();
|
let mail = mailparse::parse_mail(mail_bytes).unwrap();
|
||||||
println!(
|
println!(
|
||||||
"{:?} {:?} from {:?}",
|
"{:?} {:?} from {:?}",
|
||||||
match mail.headers.get_first_value("Date")? {
|
match mail.headers.get_first_value("Date") {
|
||||||
Some(date) => date,
|
Some(date) => date,
|
||||||
None => "NO DATE".to_string(),
|
None => "NO DATE".to_string(),
|
||||||
},
|
},
|
||||||
match mail.headers.get_first_value("Subject")? {
|
match mail.headers.get_first_value("Subject") {
|
||||||
Some(subject) => subject,
|
Some(subject) => subject,
|
||||||
None => "NO SUBJECT".to_string(),
|
None => "NO SUBJECT".to_string(),
|
||||||
},
|
},
|
||||||
match mail.headers.get_first_value("From")? {
|
match mail.headers.get_first_value("From") {
|
||||||
Some(from) => from,
|
Some(from) => from,
|
||||||
None => "NO FROM".to_string(),
|
None => "NO FROM".to_string(),
|
||||||
},
|
},
|
||||||
|
|||||||
53
src/lib.rs
Normal file
53
src/lib.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use mailparse::{parse_headers, MailHeader, MailHeaderMap};
|
||||||
|
use sha1::{Digest, Sha1};
|
||||||
|
|
||||||
|
// Keep these sorted to match Go implementation.
|
||||||
|
const IMPORTANT_HEADERS: &[&str] = &[
|
||||||
|
"cc",
|
||||||
|
"date",
|
||||||
|
"from",
|
||||||
|
"message-id",
|
||||||
|
"received",
|
||||||
|
"subject",
|
||||||
|
"to",
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn hash_headers(hdrs: &[MailHeader]) -> String {
|
||||||
|
// create a Sha1 object
|
||||||
|
let mut hasher = Sha1::new();
|
||||||
|
|
||||||
|
for h in IMPORTANT_HEADERS {
|
||||||
|
if let Some(v) = hdrs.get_first_value(h) {
|
||||||
|
eprintln!("V [{}]", v);
|
||||||
|
hasher.update(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format!("{:x}", hasher.finalize())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use mailparse::{parse_headers, MailHeader, MailHeaderMap};
|
||||||
|
#[test]
|
||||||
|
fn hash_headers() {
|
||||||
|
let (hdrs, _) = parse_headers(
|
||||||
|
concat!(
|
||||||
|
"Subject: Test\n",
|
||||||
|
"From: me@myself.com\n",
|
||||||
|
"To: you@yourself.com"
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(hdrs[1].get_key(), "From");
|
||||||
|
assert_eq!(
|
||||||
|
hdrs.get_first_value("To"),
|
||||||
|
Some("you@yourself.com".to_string())
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
super::hash_headers(&hdrs),
|
||||||
|
"1b25d59ed0ade6a762145c58643717477b054fd1"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user