8.4. Howdy Email API

This document describes the lower level Plex emailing API, upon which the command line tol and the GUI tool are built. It lives in howdy.email.

8.4.1. howdy.email module

This contains the lowest level methods to send email using either the Google Contacts API or through Python’s SMTP functionality, and to find the Google contact names of friend emails on the Plex server. HowdyIMGClient and PNGPicObject allow one to add or remove images from one’s Imgur acount.

class howdy.email.HowdyIMGClient(verify=True, data_imgurl=None)

This object contains and implements the collection of images located in a single main album in the Imgur account. This uses the Imgur API to peform all operations. This object is constructed using Imgur credentials – the client ID, secret, and refresh token – stored in the SQLite3 configuration database, and stores the following attributes: the client ID, secret, refresh token, and the access token used for API access to your Imgur album and images.

If the Imgur albums cannot be accessed, or there are no albums, then self.albumID = None, the self.imgHashes is an empty dict.

The main album ID is stored as a string in the Imgur configuration under the mainALBUMID key, if it exists; otherwise the Imgur configuration dictionary does not have a mainALBUMID key.

  • If there is no main album ID defined, or if there is no album with that ID, then we choose the first album found, and reset the Imgur configuration data into the SQLite3 database with this album ID and name.
  • If the configured album exists in our Imgur library, then continue with this the main album.

Once the main album is found, populate self.imghashes with all the pictures in this album. The pictures in an album in our Imgur account are expected to be filled through methods in this object.

  • The key is the MD5 hash of the image in that library.
  • The value is a four element tuple: image name, image ID, the URL link to this image, and the datetime at which the image was uploaded.
Parameters:
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • data_imgurl (dict) – optional argument. If defined, must have the following keys: clientID, clientSECRET, and clientREFRESHTOKEN. Must be consistent with dict returned by get_imgurl_credentials.
Variables:
  • verify (bool) – whether to verify SSL connections.
  • access_token (str) – the persistent API access token to the user’s Imgur account.
  • clientID (str) – the Imgur client ID.
  • clientSECRET (str) – the Imgur client secret.
  • albumID (str) – the hashed name of the main album.
  • imghashes (dict) – the structure of images stored in the main album.
Raises:

ValueError – if images in the new album cannot be accessed.

See also

refreshImages.

change_album_name(new_album_name)

Changes the main album name to a new name, only if the new name is different from the old name.

Parameters:new_album_name (str) – the new name to change the main Imgur album.

See also

refreshImages.

change_name(imgMD5, new_name)

Changes the name of an image in the main Imgur library.

Parameters:
  • imgMD5 (str) – this is the MD5 hash of the image in the main Imgur library.
  • new_name (str) – the new name to give this image.
Returns:

True if image could be found and its name changed. Otherwise returns False.

Return type:

bool

delete_candidate_album(candidate_album_name)

This deletes the candidate album from the Imgur account. This album with that name must exist in the Imgur account.

Parameters:candidate_album_name (str) – the name of the album to remove, with its underlying images.

See also

refreshImages.

delete_image(b64img, imgMD5=None)

Removes an image from the main Imgur library.

Parameters:
  • b64img (str) – the Base64 representation of the image.
  • imgMD5 (str) – optional argument. This is the MD5 hash of the image. If not provided, this is calculated for that image represented by b64img.
Returns:

True if image can be found and returned. Otherwise returns False.

Return type:

bool

get_candidate_album_names()
Returns:a list of album names in the Imgur account. set_main_album can use this method to determine the valid album name to choose.

See also

get_candidate_albums.

get_candidate_albums()
Returns:a dict of album information, organized by album name. Each key in the top-level dictionary is the album name. Each value is a lower level dictionary: the id key is the album ID, and the images key is a list of low-level Imgur image information.
classmethod get_image_md5(image)
Returns:the MD5 hash of the image.
Parameters:image (PngImageFile) – the native Pillow PNG image object.
get_main_album_name()
Returns:the name of the main Imgur album, if albums exist on this account. Otherwise returns None.
Return type:str
refreshImages()

Refreshes the collection of images in the main Imgur album, by filling out self.imghashes. The pictures in an album in our Imgur account are expected to be filled through methods in this object.

  • The key is the MD5 hash of the image in that library.
  • The value is a four element tuple: image name, image ID, the URL link to this image, and the datetime at which the image was uploaded.
set_main_album(new_album_name)

Sets or changes the main Imgur album used for storing and displaying images to a new album name. If new_album_name exists in the Imgur account, then sets that name. If new_album_name does not exist, then creates this new Imgur album.

Once this album is set or created,

  • sets the new Imgur credentials using store_imgur_credentials.
  • populates self.imghashes with all the images found in this library. Of course, if the album does not exist, then self.imghashes is an empty dict.
Parameters:new_album_name (str) – the new name of the Imgur album to use for images.
Raises:ValueError – if images in the new album cannot be accessed.

See also

refreshImages.

upload_image(b64img, name, imgMD5=None)

Uploads a Base64 encoded file into the main Imgur album. If the image exists, then returns information (from self.imghashes) about the file. If not, create it, put it into self.imghashes, and then return its information.

Parameters:
  • b64img (str) – the Base64 representation of the image.
  • name (str) – name of the image.
  • imgMD5 (str) – optional argument. This is the MD5 hash of the image. If not provided, this is calculated for that image represented by b64img.
Returns:

a 4-element tuple: image name, image ID, the URL link to this image, and the datetime at which the image was uploaded.

Return type:

tuple

class howdy.email.PNGPicObject(initdata, pImgClient)

This provides a GUI widget to the Imgur interface implemented in PlexIMGClient. Initializaton of the image can either upload this image to the Imgur account, or retrieve the image from the main Imgur album. This object can also launch a GUI dialog window through getInfoGUI.

Parameters:
  • initdata (dict) –

    the low-level dictionary that contains important information on the image, located in a file, that will either be uploaded into the main Imgur album or merely kept in memory. The main key that determines operation is initialization. It can be one of "FILE" or "SERVER".

    If initialization is "FILE", then upload the the image to the main album in the Imgur account. Here are the required keys in initdata.

    • filename is the location of the image file on disk.
    • actName is the PNG filename to be used. It must end in png.

    If initialization is "SERVER", then retrieve this image from the main album in the Imgur account. Here are the required keys in initdata.

    • imgurlink is the URL link to the image.
    • imgName is the name of the image.
    • imgMD5 is the MD5 hash of the image.
    • imgDateTime is the datetime at which the image was initially uploaded into the main Imgur album.
  • pImgClient (PlexIMGClient) – the PlexIMGClient used to access and manipulate (add, delete, rename) images in the main Imgur album.
Variables:
  • actName (str) – the file name without full path, which must end in png.
  • img (QImage) – the QImage representation of this image.
  • originalImage (Image) – the Image representation of this image.
  • originalWidth (float) – the inferred width in cm.
  • currentWidth (float) – the current image width in cm. It starts off as equal to originalWidth
  • b64string (str) – the Base64 encoded representation of this image as a PNG file.
  • imgurlLink (str) – the URL link to the image.
  • imgDateTime (datetime) – the datetime at which this image was first uploaded to the main album in the Imgur account.
Raises:

ValueError – if initdata['initialization'] is neither "FILE" nor "SERVER".

b64String()
Returns:a 3-element tuple on the image incorporated into this object: its Base64 string, its width in pixels, and the Imgur link.
Return type:tuple
changeName(new_name, hImgClient)

changes the filename into a new name.

Parameters:
  • new_name (str) – the new name of the image file to be changed in the main album on the Imgur account. This must end in png.
  • hImgClient (HowdyIMGClient) – the HowdyIMGClient used to access and manipulate (add, delete, rename) images in the main Imgur album.
classmethod createPNGPicObjects(pImgClient)
Parameters:pImgClient (PlexIMGClient) – the PlexIMGClient used to access and manipulate (add, delete, rename) images in the main Imgur album.
Returns:a list of PNGPicObject representing the images in the main Imgur album.
Return type:list
getInfoGUI(parent)

Launches a QDialog that contains the underlying image and some other labels: ACTNAME is the actual PNG file name, URL is the image’s Imgur link, and UPLOADED AT is the date and time at which the file was uploaded. An example image is shown below,

../_images/email_pngpicobject_infogui.png

Fig. 8.36 An example PNG image that can be stored in the main Imgur library. Note the three rows above the image: the name of the PNG image; its URL; and the date and time it was uploaded.

Parameters:parent (QWidget) – the parent QWidget that acts as the QDialog window’s parent. Can be None.
howdy.email.get_all_email_contacts_dict(verify=True, pagesize=4000)

Returns all the Google contacts using the Google Contacts API.

Parameters:
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • pagesize (int) – optional argument, the maximum number of candidate contacts to search through. Must be \(\ge 1\).
Returns:

a dict of contacts. The key is the contact name, and the value is the set of email addresses for that contact.

Return type:

dict

howdy.email.get_email_contacts_dict(emailList, verify=True)

Returns the Google contacts given a set of emails, all using the Google Contacts API.

Parameters:
  • emailList (list) – the list of emails, used to determine to whom it belongs.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
Returns:

a list of two-element tuple. The first element is the Google conatct name. The second element is a primary email associated with that contact.

Return type:

list

howdy.email.get_email_service(verify=True)

This returns a working Resource representing the Google email service used to send and receive emails.

Parameters:verify (bool) – optional argument, whether to verify SSL connections. Default is True.
Returns:the Resource representing the Google email service used to send and receive emails. If None, then generated here.
Return type:Resource
howdy.email.send_email_localsmtp(msg)

Sends the email using the SMTP Python functionality to send through a local SMTP server. This blog post describes how I set up a GMail relay using my local SMTP server on my Ubuntu machine.

Parameters:msg (MIMEMultiPart) – the MIMEMultiPart email message to send. At a high level, this is an email with body, sender, recipients, and optional attachments.
howdy.email.send_email_lowlevel(msg, email_service=None, verify=True)

Sends out an email using the Google Contacts API. If process is unsuccessfull, prints out an error message, "problem with <TO-EMAIL>", where <TO-EMAIL> is the recipient’s email address.

Parameters:
  • msg (MIMEMultiPart) – the MIMEMultiPart email message to send. At a high level, this is an email with body, sender, recipients, and optional attachments.
  • email_service – optional argument, the Resource representing the Google email service used to send and receive emails. If None, then generated here.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.

See also

get_email_service.

8.4.2. howdy.email.email module

This implements the following functionality: sending emails of torrent files and magnet links; sending MIMEMultiPart newsletter or more general style emails to friends of the Plex server; and sending general emails with attachments.

howdy.email.email.get_summary_body(token, nameSection=False, fullURL='http://localhost:32400', verify=True)

Returns the summary body of the Plex newsletter email as a reStructuredText string document, for the Plex server.

Parameters:
  • token (str) – the Plex access token.
  • nameSection (bool) – if True, then include this summary in its own section called "Summary". If not, then return as a stand-alone reStructuredText document.
  • fullURL (str) – the Plex server URL.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
Returns:

the reStructuredText document representing the summary of the media on the Plex server.

Return type:

str

howdy.email.email.get_summary_data_movies_remote(token, fullURL='http://localhost:32400', sinceDate=datetime.date(2020, 1, 1))

This returns summary information on movie media from all movie libraries on the Plex server, for use as part of the Plex newsletter sent out to one’s Plex server friends. The email first summarizes ALL the movie data, and then summarizes the movie data uploaded and processed since the last newsletter’s date. Unlike get_summary_data_music_remote and get_summary_data_television_remote, this returns a list of strings rather than a string.

Parameters:
  • token (str) – the Plex access token.
  • fullURL (str) – the Plex server URL.
Returns:

a string description of TV media in all TV libraries on the Plex server. If there is no Plex server or TV library, returns None.

Return type:

list

See also

get_summary_body.

howdy.email.email.get_summary_data_music_remote(token, fullURL='http://localhost:32400', sinceDate=datetime.date(2020, 1, 1))

This returns summary information on songs from all music libraries on the Plex server, for use as part of the Plex newsletter sent out to one’s Plex server friends. The email first summarizes ALL the music data, and then summarizes the music data uploaded and processed since a previous date. For example,

As of December 29, 2020, there are 17,853 songs made by 889 artists in 1,764 albums. The total size of music media is 306.979 GB. The total duration of music media is 7 months, 18 days, 15 hours, 8 minutes, and 15.785 seconds.

Since January 01, 2020, I have added 7,117 songs made by 700 artists in 1,180 albums. The total size of music media that I have added is 48.167 GB. The total duration of music media that I have added is 28 days, 15 hours, 25 minutes, and 37.580 seconds.

Parameters:
  • token (str) – the Plex access token.
  • fullURL (str) – the Plex server URL.
  • sinceDate (date) – the datetime from which we have added songs. Default is date corresponding to January 1, 2020.
Returns:

a string description of music media in all music libraries on the Plex server. If there is no Plex server or music library, returns None.

Return type:

str

See also

get_summary_body.

howdy.email.email.get_summary_data_television_remote(token, fullURL='http://localhost:32400', sinceDate=datetime.date(2020, 1, 1))

This returns summary information on TV media from all television libraries on the Plex server, for use as part of the Plex newsletter sent out to one’s Plex server friends. The email first summarizes ALL the TV data, and then summarizes the TV data uploaded and processed since a previous date. For example,

As of December 29, 2020, there are 25,195 TV episodes in 298 TV shows. The total size of TV media is 6.690 TB. The total duration of TV media is 1 year, 5 months, 19 days, 9 hours, 29 minutes, and 13.919 seconds.

Since January 01, 2020, I have added 5,005 TV epsisodes in 298 TV shows. The total size of TV media that I have added is 1.571 TB. The total duration of TV media that I have added is 3 months, 16 days, 4 hours, 52 minutes, and 15.406 seconds.

Parameters:
  • token (str) – the Plex access token.
  • fullURL (str) – the Plex server URL.
  • sinceDate (date) – the datetime from which we have added songs. Default is date corresponding to January 1, 2020.
Returns:

a string description of TV media in all TV libraries on the Plex server. If there is no Plex server or TV library, returns None.

Return type:

str

See also

get_summary_body.

howdy.email.email.get_summary_html(token, fullURL='http://localhost:32400', preambleText='', postambleText='', name=None)

Creates a Plex newsletter summary HTML email of the media on the Plex server. Used by the email GUI to send out summary emails.

Parameters:
  • token (str) – the Plex access token.
  • fullURL (str) – the Plex server URL.
  • preambleText (str) – optional argument. The reStructuredText formatted preamble text (text section before summary), if non-empty. Default is "".
  • postambleText (str) – optional argument. The reStructuredText formatted text, in a section after the summary. if non-empty. Default is "".
  • name (str) – optional argument. If given, the recipient’s name.
Returns:

a two-element tuple. The first element is an HTML string document of the Plex newletter email. The second element is the full reStructuredText string.

Return type:

str

See also

get_summary_body.

howdy.email.email.send_collective_email_full(mainHTML, subject, fromEmail, to_emails, cc_emails, bcc_emails, verify=True, email_service=None)

Sends the HTML email to the following TO recipients, CC recipients, and BCC recipients altogether. It uses the GMail API.

Parameters:
  • mainHTML (str) – the email body as an HTML string document.
  • subject (str) – the email subject.
  • fromEmail (str) – the RFC 2047 sender’s email with name.
  • to_emails (set) – the RFC 2047 set of TO recipients.
  • cc_emails (set) – the RFC 2047 set of CC recipients.
  • bcc_emails (set) – the RFC 2047 set of BCC recipients.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • email_service – optional argument, the Resource representing the Google email service used to send and receive emails. If None, then generated here.
howdy.email.email.send_email_movie_none(movieName, verify=True)

Request an individual movie from the Plex server’s administrator, using the GMail API.

Parameters:
  • movieName (str) – the name of the movie.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
Returns:

the string "SUCCESS" if nothing goes wrong.

Return type:

str

Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_email_movie_torrent(movieName, data, isJackett=False, verify=True)

Sends an individual torrent file or magnet link to the Plex user’s email, using the GMail API.

Parameters:
  • movieName (str) – the name of the movie.
  • data (str) – the Base64 encoded file, if torrent file. Otherwise the magnet URI link if magnet link.
  • isJackett (bool) – boolean flag used to determine whether data is a torrent file or magnet link. If False, then expects a torrent file. If True, then expects a magnet link. Default is False.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
Returns:

the string "SUCCESS" if nothing goes wrong.

Return type:

str

Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_individual_email(mainHTML, email, name=None, mydate=datetime.date(2021, 1, 3), verify=True, email_service=None)

sends the HTML email to a single recipient email address using the GMail API. The subject is "Plex Email Newsletter for <MONTH> <YEAR>".

Parameters:
  • mainHTML (str) – the email body as an HTML str document.
  • email (str) – the recipient email address.
  • name (str) – optional argument. If given, the recipient’s name.
  • mydate (date) – optional argument. The date at which the email is sent. Default is now( ).
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • email_service – optional argument, the Resource representing the Google email service used to send and receive emails. If None, then generated here.
Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_individual_email_full(mainHTML, subject, emailAddress, name=None, attach=None, attachName=None, attachType='txt', verify=True, email_service=None)

Sends the HTML email, with optional single attachment, to a single recipient email address, using the GMail API. Unlike send_individual_email_full_withsingleattach, the attachment type is also set.

Parameters:
  • mainHTML (str) – the email body as an HTML str document.
  • subject (str) – the email subject.
  • emailAddress (str) – the recipient email address.
  • name (str) – optional argument. If given, the recipient’s name.
  • mydate (date) – optional argument. The date at which the email is sent. Default is now( ).
  • attach (str) – optional argument. If defined, the Base64 encoded attachment.
  • attachName (str) – optional argument. The list of attachment names, if there is an attachment. If defined, then attachData must also be defined.
  • attachType (str) – the attachment type. Default is txt.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • email_service – optional argument, the Resource representing the Google email service used to send and receive emails. If None, then generated here.
Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_individual_email_full_withattachs(mainHTML, subject, email, name=None, attachNames=None, attachDatas=None)

Sends the HTML email, with optional attachments, to a single recipient email address. This uses the SMTP Python functionality to send through a local SMTP server (see send_email_localsmtp).

Parameters:
  • mainHTML (str) – the email body as an HTML str document.
  • subject (str) – the email subject.
  • email (str) – the recipient email address.
  • name (str) – optional argument. If given, the recipient’s name.
  • mydate (date) – optional argument. The date at which the email is sent. Default is now( ).
  • attachNames (list) – optional argument. The list of attachment names, if attachments are used. If defined, then attachDatas must also be defined.
  • attachDatas (list) – optional argument. If defined, the list of attachments with corresponding name described in attachNames. Each entry is a Base64 encoded attachment.
Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_individual_email_full_withsingleattach(mainHTML, subject, email, name=None, attachData=None, attachName=None, verify=True, email_service=None)

Sends the HTML email, with optional single attachment, to a single recipient email address, using the GMail API.

Parameters:
  • mainHTML (str) – the email body as an HTML str document.
  • subject (str) – the email subject.
  • email (str) – the recipient email address.
  • name (str) – optional argument. If given, the recipient’s name.
  • mydate (date) – optional argument. The date at which the email is sent. Default is now( ).
  • attachData (str) – optional argument. If defined, the Base64 encoded attachment.
  • attachName (str) – optional argument. The list of attachment names, if there is an attachment. If defined, then attachData must also be defined.
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.
  • email_service – optional argument, the Resource representing the Google email service used to send and receive emails. If None, then generated here.
Raises:

AssertionError – if the current Plex account user’s email address does not exist.

howdy.email.email.send_individual_email_perproc(input_tuple)

A tuple-ized version of send_individual_email used by the multiprocessing module to send out emails.

Parameters:input_tuple (tuple) – an expected four-element tuple: the HTML email body, the recipient’s email, the recipient’s name, and the email service resource.
howdy.email.email.test_email(subject=None, htmlstring=None, verify=True)

Sends a test email to the Plex user’s email address.

Parameters:
  • subject (str) – optional argument. The email subject. If not defined, the subject is "Plex Email Newsletter for <MONTH> <YEAR>".
  • htmlstring (str) – optional argument. The email body as an HTML str document. If not defined, the body is "This is a test.".
  • verify (bool) – optional argument, whether to verify SSL connections. Default is True.