Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Renamed error field and improved logging #35

Merged
merged 18 commits into from Dec 4, 2017
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Expand Up @@ -143,10 +143,12 @@ The following values are returned in `results.csv`:

#### Etc.

* `Syntax Errors` - A list of syntax errors that were detected when
scanning DMARC or SPF records, or checking for STARTTLS support.
* `Errors` - A list of any other errors encountered, such as DNS
failures.
* `Syntax Errors` - A list of syntax errors that were encountered when
analyzing SPF records.
* `Debug` - A list of any other warnings or errors encountered, such
as DNS failures. These can be helpful when determining how
`trustymail` reached its conclusions, and are indispensible for bug
reports.

## Public domain

Expand Down
16 changes: 9 additions & 7 deletions trustymail/cli.py
Expand Up @@ -37,10 +37,10 @@
"""
from trustymail import __version__
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're shuffling imports around, I would move this one to before the from trustymail import trustymail line below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I'll make the change.


import logging
import docopt
import os
import errno
import logging
import os

from trustymail import trustymail

Expand All @@ -51,8 +51,10 @@
def main():
args = docopt.docopt(__doc__, version=__version__)

log_level = logging.WARN
if args['--debug']:
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
log_level = logging.DEBUG
logging.basicConfig(format='%(asctime)-15s %(message)s', level=log_level)

# Allow for user to input a csv for many domain names.
if args['INPUT'][0].endswith('.csv'):
Expand Down Expand Up @@ -91,10 +93,10 @@ def main():

# User might not want every scan performed.
scan_types = {
"mx": args["--mx"],
"starttls": args["--starttls"],
"spf": args["--spf"],
"dmarc": args["--dmarc"]
'mx': args['--mx'],
'starttls': args['--starttls'],
'spf': args['--spf'],
'dmarc': args['--dmarc']
}

domain_scans = []
Expand Down
66 changes: 33 additions & 33 deletions trustymail/domain.py
Expand Up @@ -17,7 +17,7 @@ def __init__(self, domain_name, timeout, smtp_timeout, smtp_localhost, smtp_port
if self.base_domain_name != self.domain_name:
if self.base_domain_name not in Domain.base_domains:
# Populate DMARC for parent.
domain = trustymail.scan(self.base_domain_name, timeout, smtp_timeout, smtp_localhost, smtp_ports, smtp_cache, {"mx": False, "starttls": False, "spf": False, "dmarc": True}, dns_hostnames)
domain = trustymail.scan(self.base_domain_name, timeout, smtp_timeout, smtp_localhost, smtp_ports, smtp_cache, {'mx': False, 'starttls': False, 'spf': False, 'dmarc': True}, dns_hostnames)
Domain.base_domains[self.base_domain_name] = domain
self.base_domain = Domain.base_domains[self.base_domain_name]
else:
Expand Down Expand Up @@ -47,8 +47,8 @@ def __init__(self, domain_name, timeout, smtp_timeout, smtp_localhost, smtp_port
# 3. Whether or not the server supports STARTTLS
self.starttls_results = {}

# A list of any errors that occurred while scanning records.
self.errors = []
# A list of any debugging information collected while scanning records.
self.debug = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit leery of the name .debug as that makes me think of a boolean flag more than a list... maybe .debug_info would be more descriptive?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll make the change.


# A list of the ports tested for SMTP
self.ports_tested = set()
Expand All @@ -61,15 +61,15 @@ def has_supports_smtp(self):
Returns True if any of the mail servers associated with this
domain are listening and support SMTP.
"""
return len(filter(lambda x: self.starttls_results[x]["supports_smtp"],
return len(filter(lambda x: self.starttls_results[x]['supports_smtp'],
self.starttls_results.keys())) > 0

def has_starttls(self):
"""
Returns True if any of the mail servers associated with this
domain are listening and support STARTTLS.
"""
return len(filter(lambda x: self.starttls_results[x]["starttls"],
return len(filter(lambda x: self.starttls_results[x]['starttls'],
self.starttls_results.keys())) > 0

def has_spf(self):
Expand Down Expand Up @@ -101,49 +101,49 @@ def parent_dmarc_results(self):

def get_dmarc_policy(self):
# If the policy was never set, or isn't in the list of valid policies, check the parents.
if self.dmarc_policy is None or self.dmarc_policy.lower() not in ["quarantine", "reject", "none"]:
if self.dmarc_policy is None or self.dmarc_policy.lower() not in ['quarantine', 'reject', 'none']:
if self.base_domain is None:
return ""
return ''
else:
return self.base_domain.get_dmarc_policy()
return self.dmarc_policy

def generate_results(self):
mail_servers_that_support_smtp = [x for x in self.starttls_results.keys() if self.starttls_results[x]["supports_smtp"]]
mail_servers_that_support_starttls = [x for x in self.starttls_results.keys() if self.starttls_results[x]["starttls"]]
mail_servers_that_support_smtp = [x for x in self.starttls_results.keys() if self.starttls_results[x]['supports_smtp']]
mail_servers_that_support_starttls = [x for x in self.starttls_results.keys() if self.starttls_results[x]['starttls']]
domain_supports_smtp = bool(mail_servers_that_support_starttls)

results = {
"Domain": self.domain_name,
"Base Domain": self.base_domain_name,
"Live": self.is_live,

"MX Record": self.has_mail(),
"Mail Servers": self.format_list(self.mail_servers),
"Mail Server Ports Tested": self.format_list([str(port) for port in self.ports_tested]),
"Domain Supports SMTP Results": self.format_list(mail_servers_that_support_smtp),
'Domain': self.domain_name,
'Base Domain': self.base_domain_name,
'Live': self.is_live,

'MX Record': self.has_mail(),
'Mail Servers': self.format_list(self.mail_servers),
'Mail Server Ports Tested': self.format_list([str(port) for port in self.ports_tested]),
'Domain Supports SMTP Results': self.format_list(mail_servers_that_support_smtp),
# True if and only if at least one mail server speaks SMTP
"Domain Supports SMTP": domain_supports_smtp,
"Domain Supports STARTTLS Results": self.format_list(mail_servers_that_support_starttls),
'Domain Supports SMTP': domain_supports_smtp,
'Domain Supports STARTTLS Results': self.format_list(mail_servers_that_support_starttls),
# True if and only if all mail servers that speak SMTP
# also support STARTTLS
"Domain Supports STARTTLS": domain_supports_smtp and all([self.starttls_results[x]["starttls"] for x in mail_servers_that_support_smtp]),
'Domain Supports STARTTLS': domain_supports_smtp and all([self.starttls_results[x]['starttls'] for x in mail_servers_that_support_smtp]),

"SPF Record": self.has_spf(),
"Valid SPF": self.valid_spf,
"SPF Results": self.format_list(self.spf),
'SPF Record': self.has_spf(),
'Valid SPF': self.valid_spf,
'SPF Results': self.format_list(self.spf),

"DMARC Record": self.has_dmarc(),
"Valid DMARC": self.has_dmarc() and self.valid_dmarc,
"DMARC Results": self.format_list(self.dmarc),
'DMARC Record': self.has_dmarc(),
'Valid DMARC': self.has_dmarc() and self.valid_dmarc,
'DMARC Results': self.format_list(self.dmarc),

"DMARC Record on Base Domain": self.parent_has_dmarc(),
"Valid DMARC Record on Base Domain": self.parent_has_dmarc() and self.parent_valid_dmarc(),
"DMARC Results on Base Domain": self.parent_dmarc_results(),
"DMARC Policy": self.get_dmarc_policy(),
'DMARC Record on Base Domain': self.parent_has_dmarc(),
'Valid DMARC Record on Base Domain': self.parent_has_dmarc() and self.parent_valid_dmarc(),
'DMARC Results on Base Domain': self.parent_dmarc_results(),
'DMARC Policy': self.get_dmarc_policy(),

"Syntax Errors": self.format_list(self.syntax_errors),
"Errors": self.format_list(self.errors)
'Syntax Errors': self.format_list(self.syntax_errors),
'Debug': self.format_list(self.debug)
}

return results
Expand All @@ -157,4 +157,4 @@ def format_list(self, record_list):
if not record_list:
return None

return ", ".join(record_list)
return ', '.join(record_list)