A Mail Command in Python - 01 A Command Line App
Tags: python, linux, beginners, tutorial
Published: 2022-04-19 01:48:39

We're going to write a tiny mail utility in python. The goal is to mimic the mail command with the same set of flags. The reason was that trying to get the mail command to handle html was a pain in the ass and involved messing with the mail headers manually. It would be much better to use python and have it do the header manipulation. I however also don't want to re-write any of the existing scripts so we want to keep the same exact interface!

The first step is to figure out which flags we'll need.

Most of my mail commands look like this:
```bash
> echo "Body" | mail -s "Subject" -c cc@address.com -a /path/to/file/Intrcall.pdf -r from@address.com to@address.com
```

I pipe the e-mail body to the mail command and then set the subject, any cc addresses, add attachments, set the from address and finally set the destination.

The goal is to write a python version that could read in the above command and do the same thing as the mail command.

Let's get started!

## argparse

Python has a builtin library to handle command line arguments that works quite well. There is quite a bit of magic in this library which I don't like but the results speak for themselves. You can get a pretty command line program up and running very easily with python.

The first snippet of code to run is this:

```python
#!/usr/bin/env python3

import argparse

def main():
    parser = argparse.ArgumentParser()
    args = parser_args()

main()
```

You can save this without the .py extension as this will be an executable we run. I named the program pymail. (Very creative).

I have also set the shebang(\#!) to reference python3 using the env. This is because I don't know where this script will run and which version of python I might have or where it would be. This makes it so that whatever is linked python3 will be used to run this script.

Now we need to mark the program as executable:
```bash
> chmod +x pymail
```

Now you can execute the program:

```bash
> ./pymail
>
```

Voila! We get nothing! A bit underwhelming but! so much magic has happened.

Try the following:
```bash
> ./pymail -h
```

You should see the below screen. By using the argparse library we get some pretty help text and it sets up the first flag for us.
```bash
usage: pymail [-h]

optional arguments:
  -h, --help  show this help message and exit
```

Let's add a more descriptive help text.
```python
    parser = argparse.ArgumentParser(description="Mail replacement in python.")
```

This will now print our description when someone looks for help.

```bash
> ./pymail -h
usage: pymail [-h]

Mail replacement in python.

optional arguments:
  -h, --help  show this help message and exit
```

We can also add an epilog to print some text after all of our flags as well.

```python
    parser = argparse.ArgumentParser(description="Mail replacement in python", epilog="* not a meal replacement *")
```

This would print out:

```bash
> ./pymail -h
usage: pymail [-h]

Mail replacement in python.

optional arguments:
  -h, --help  show this help message and exit

* not a meal replacement *
```

Now we have argparse set up and ready to be used. In the next chapter we'll add all the flags that make a mail command useful!