mail2task 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mail2task-0.2.0 → mail2task-0.4.0}/PKG-INFO +23 -2
- {mail2task-0.2.0 → mail2task-0.4.0}/README.md +22 -1
- {mail2task-0.2.0 → mail2task-0.4.0}/pyproject.toml +1 -1
- mail2task-0.4.0/src/mail2task/cli.py +99 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task/extractor.py +38 -2
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/PKG-INFO +23 -2
- mail2task-0.2.0/src/mail2task/cli.py +0 -52
- {mail2task-0.2.0 → mail2task-0.4.0}/setup.cfg +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task/__init__.py +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task/parser.py +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/SOURCES.txt +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/dependency_links.txt +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/entry_points.txt +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/requires.txt +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/src/mail2task.egg-info/top_level.txt +0 -0
- {mail2task-0.2.0 → mail2task-0.4.0}/tests/test_extractor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mail2task
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Extract actionable tasks from emails using Python
|
|
5
5
|
Author: Eby J Kavungal
|
|
6
6
|
Project-URL: Homepage, https://github.com/EbyJK/mail2task
|
|
@@ -77,7 +77,9 @@ Output:
|
|
|
77
77
|
{
|
|
78
78
|
"title": "submit the report by Friday.",
|
|
79
79
|
"due_date": "2026-05-29T00:00:00",
|
|
80
|
-
"priority": "normal"
|
|
80
|
+
"priority": "normal",
|
|
81
|
+
"confidence": 0.9
|
|
82
|
+
|
|
81
83
|
}
|
|
82
84
|
]
|
|
83
85
|
```
|
|
@@ -94,6 +96,25 @@ mail2task sample_email.txt --pretty
|
|
|
94
96
|
mail2task sample_email.txt --output tasks.json
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
|
|
100
|
+
## Export Formats
|
|
101
|
+
|
|
102
|
+
### JSON
|
|
103
|
+
```bash
|
|
104
|
+
mail2task sample_email.txt --format json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### CSV
|
|
108
|
+
```bash
|
|
109
|
+
mail2task sample_email.txt --format csv
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Markdown
|
|
113
|
+
```bash
|
|
114
|
+
mail2task sample_email.txt --format markdown
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
97
118
|
---
|
|
98
119
|
|
|
99
120
|
## Example Use Cases
|
|
@@ -62,7 +62,9 @@ Output:
|
|
|
62
62
|
{
|
|
63
63
|
"title": "submit the report by Friday.",
|
|
64
64
|
"due_date": "2026-05-29T00:00:00",
|
|
65
|
-
"priority": "normal"
|
|
65
|
+
"priority": "normal",
|
|
66
|
+
"confidence": 0.9
|
|
67
|
+
|
|
66
68
|
}
|
|
67
69
|
]
|
|
68
70
|
```
|
|
@@ -79,6 +81,25 @@ mail2task sample_email.txt --pretty
|
|
|
79
81
|
mail2task sample_email.txt --output tasks.json
|
|
80
82
|
```
|
|
81
83
|
|
|
84
|
+
|
|
85
|
+
## Export Formats
|
|
86
|
+
|
|
87
|
+
### JSON
|
|
88
|
+
```bash
|
|
89
|
+
mail2task sample_email.txt --format json
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### CSV
|
|
93
|
+
```bash
|
|
94
|
+
mail2task sample_email.txt --format csv
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Markdown
|
|
98
|
+
```bash
|
|
99
|
+
mail2task sample_email.txt --format markdown
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
|
|
82
103
|
---
|
|
83
104
|
|
|
84
105
|
## Example Use Cases
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import csv
|
|
4
|
+
from .extractor import extract_tasks
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def save_csv(tasks, output_file):
|
|
8
|
+
with open(output_file, "w", newline="", encoding="utf-8") as f:
|
|
9
|
+
writer = csv.DictWriter(
|
|
10
|
+
f,
|
|
11
|
+
fieldnames=["title", "due_date", "priority", "confidence"]
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
writer.writeheader()
|
|
15
|
+
writer.writerows(tasks)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def save_markdown(tasks, output_file):
|
|
19
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
|
20
|
+
f.write("# Extracted Tasks\n\n")
|
|
21
|
+
|
|
22
|
+
for task in tasks:
|
|
23
|
+
f.write(f"## {task['title']}\n")
|
|
24
|
+
f.write(f"- Due Date: {task['due_date']}\n")
|
|
25
|
+
f.write(f"- Priority: {task['priority']}\n")
|
|
26
|
+
f.write(f"- Confidence: {task['confidence']}\n\n")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main():
|
|
30
|
+
parser = argparse.ArgumentParser(
|
|
31
|
+
description="Extract actionable tasks from emails"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"file",
|
|
36
|
+
help="Path to the email text file"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--pretty",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="Pretty print JSON output"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--format",
|
|
47
|
+
choices=["json", "csv", "markdown"],
|
|
48
|
+
default="json",
|
|
49
|
+
help="Output format"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--output",
|
|
54
|
+
help="Output file path"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
args = parser.parse_args()
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
with open(args.file, "r", encoding="utf-8") as f:
|
|
61
|
+
content = f.read()
|
|
62
|
+
|
|
63
|
+
tasks = extract_tasks(content)
|
|
64
|
+
|
|
65
|
+
# JSON handling
|
|
66
|
+
if args.format == "json":
|
|
67
|
+
result = (
|
|
68
|
+
json.dumps(tasks, indent=2)
|
|
69
|
+
if args.pretty
|
|
70
|
+
else json.dumps(tasks)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
print(result)
|
|
74
|
+
|
|
75
|
+
if args.output:
|
|
76
|
+
with open(args.output, "w", encoding="utf-8") as out:
|
|
77
|
+
out.write(result)
|
|
78
|
+
|
|
79
|
+
# CSV handling
|
|
80
|
+
elif args.format == "csv":
|
|
81
|
+
output_file = args.output or "tasks.csv"
|
|
82
|
+
|
|
83
|
+
save_csv(tasks, output_file)
|
|
84
|
+
|
|
85
|
+
print(f"CSV saved to {output_file}")
|
|
86
|
+
|
|
87
|
+
# Markdown handling
|
|
88
|
+
elif args.format == "markdown":
|
|
89
|
+
output_file = args.output or "tasks.md"
|
|
90
|
+
|
|
91
|
+
save_markdown(tasks, output_file)
|
|
92
|
+
|
|
93
|
+
print(f"Markdown saved to {output_file}")
|
|
94
|
+
|
|
95
|
+
except FileNotFoundError:
|
|
96
|
+
print(f"File not found: {args.file}")
|
|
97
|
+
|
|
98
|
+
except Exception as e:
|
|
99
|
+
print(f"Error: {e}")
|
|
@@ -59,6 +59,32 @@ def is_task_sentence(text: str):
|
|
|
59
59
|
return any(word in text_lower for word in ACTION_WORDS)
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
def calculate_confidence(text: str, due_date, priority):
|
|
63
|
+
score = 0.4
|
|
64
|
+
|
|
65
|
+
text_lower = text.lower()
|
|
66
|
+
|
|
67
|
+
# Action word boost
|
|
68
|
+
if any(word in text_lower for word in ACTION_WORDS):
|
|
69
|
+
score += 0.25
|
|
70
|
+
|
|
71
|
+
# Due date boost
|
|
72
|
+
if due_date:
|
|
73
|
+
score += 0.2
|
|
74
|
+
|
|
75
|
+
# Priority boost
|
|
76
|
+
if priority != "normal":
|
|
77
|
+
score += 0.1
|
|
78
|
+
|
|
79
|
+
# Sentence length quality
|
|
80
|
+
word_count = len(text.split())
|
|
81
|
+
|
|
82
|
+
if 4 <= word_count <= 20:
|
|
83
|
+
score += 0.05
|
|
84
|
+
|
|
85
|
+
return round(min(score, 0.99), 2)
|
|
86
|
+
|
|
87
|
+
|
|
62
88
|
def extract_tasks(email_text: str):
|
|
63
89
|
lines = email_text.splitlines()
|
|
64
90
|
|
|
@@ -89,10 +115,20 @@ def extract_tasks(email_text: str):
|
|
|
89
115
|
|
|
90
116
|
seen_titles.add(title.lower())
|
|
91
117
|
|
|
118
|
+
due_date = extract_due_date(line)
|
|
119
|
+
priority = detect_priority(line)
|
|
120
|
+
|
|
121
|
+
confidence = calculate_confidence(
|
|
122
|
+
line,
|
|
123
|
+
due_date,
|
|
124
|
+
priority
|
|
125
|
+
)
|
|
126
|
+
|
|
92
127
|
task = {
|
|
93
128
|
"title": title,
|
|
94
|
-
"due_date":
|
|
95
|
-
"priority":
|
|
129
|
+
"due_date": due_date,
|
|
130
|
+
"priority": priority,
|
|
131
|
+
"confidence": confidence
|
|
96
132
|
}
|
|
97
133
|
|
|
98
134
|
tasks.append(task)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mail2task
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Extract actionable tasks from emails using Python
|
|
5
5
|
Author: Eby J Kavungal
|
|
6
6
|
Project-URL: Homepage, https://github.com/EbyJK/mail2task
|
|
@@ -77,7 +77,9 @@ Output:
|
|
|
77
77
|
{
|
|
78
78
|
"title": "submit the report by Friday.",
|
|
79
79
|
"due_date": "2026-05-29T00:00:00",
|
|
80
|
-
"priority": "normal"
|
|
80
|
+
"priority": "normal",
|
|
81
|
+
"confidence": 0.9
|
|
82
|
+
|
|
81
83
|
}
|
|
82
84
|
]
|
|
83
85
|
```
|
|
@@ -94,6 +96,25 @@ mail2task sample_email.txt --pretty
|
|
|
94
96
|
mail2task sample_email.txt --output tasks.json
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
|
|
100
|
+
## Export Formats
|
|
101
|
+
|
|
102
|
+
### JSON
|
|
103
|
+
```bash
|
|
104
|
+
mail2task sample_email.txt --format json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### CSV
|
|
108
|
+
```bash
|
|
109
|
+
mail2task sample_email.txt --format csv
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Markdown
|
|
113
|
+
```bash
|
|
114
|
+
mail2task sample_email.txt --format markdown
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
97
118
|
---
|
|
98
119
|
|
|
99
120
|
## Example Use Cases
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import json
|
|
3
|
-
from .extractor import extract_tasks
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def main():
|
|
7
|
-
parser = argparse.ArgumentParser(
|
|
8
|
-
description="Extract actionable tasks from emails"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
parser.add_argument(
|
|
12
|
-
"file",
|
|
13
|
-
help="Path to the email text file"
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
parser.add_argument(
|
|
17
|
-
"--pretty",
|
|
18
|
-
action="store_true",
|
|
19
|
-
help="Pretty print the output"
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
parser.add_argument(
|
|
23
|
-
"--output",
|
|
24
|
-
help="Save output to a JSON file"
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
args = parser.parse_args()
|
|
28
|
-
|
|
29
|
-
try:
|
|
30
|
-
with open(args.file, "r", encoding="utf-8") as f:
|
|
31
|
-
content = f.read()
|
|
32
|
-
|
|
33
|
-
tasks = extract_tasks(content)
|
|
34
|
-
|
|
35
|
-
if args.pretty:
|
|
36
|
-
result = json.dumps(tasks, indent=2)
|
|
37
|
-
else:
|
|
38
|
-
result = json.dumps(tasks)
|
|
39
|
-
|
|
40
|
-
print(result)
|
|
41
|
-
|
|
42
|
-
if args.output:
|
|
43
|
-
with open(args.output, "w", encoding="utf-8") as out_file:
|
|
44
|
-
out_file.write(result)
|
|
45
|
-
|
|
46
|
-
print(f"\nSaved output to {args.output}")
|
|
47
|
-
|
|
48
|
-
except FileNotFoundError:
|
|
49
|
-
print(f"File not found: {args.file}")
|
|
50
|
-
|
|
51
|
-
except Exception as e:
|
|
52
|
-
print(f"Error: {e}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|