Package: manokit
ManokitTable of contentsGeneral InformationInstallationv1 vs. v2StructureEmail classInitializationAuthenticationAdding recipientsComposing an emailCustom Email ValidationAdding attachmentsAttachment size limitSending an emailMethod chainingExceptionsNotAValidEmailAddressErrorEmailErrorAttachmentErrorChangelogGeneral informationManokit is a simple, fully native library for sending emails. It provides an easy-to-use API for creating and sending emails, as well as offers a very customizable structure.Manokit provides 2 modules: the base module namemanokit, where theEmailbase class is defined, and a module calledmanokit.exceptionswhere custom exceptions, used by manokit, are defined.InstallationManokit can be installed from thePyPIusing the following command:pip install manokitYou can also download the package from thereleasessection, or assemble it from source.V1 vs. V2Manokit has reached a point of version separation. Manokit v2's API has been overhauled to provide a more consistent and predictable experience.These changes include:All functionality has been moved to a single class, instead of being scattered across 3 classes.Explicit type checking was removedComplete overhaul of properties and their behavioursSee additional info in ourChangelog.All these changes and updates are aimed at bringing a more pleasant experience to the end user, but they break compatibility. If you are currently using manokit and want to upgrade, make sure to update your codebase accordingly.StructureThis section describes the parts of Manokit, and how to use them.Email classTheEmailclass is where all the functionality resides.InitializationTo begin working with Manokit, simply import theEmailclass and create an instance.frommanokitimportEmailemail=Email(smtp_host="smtp.gmail.com",smtp_port=587)During initialization you can also adjust the attachment size limit (seeattachment size limitfor details), by specifying the new limit in bytes, like this:frommanokitimportEmailsmall_email=Email("smtp.gmail.com",587,filesize_limit=100)In the example above we have reduced the attachment size limit from 25 MB to 100 bytes.AuthenticationIn order to send an email, the client must first authenticate themselves with their SMTP server. Using Manokit, the authentication process looks like this:frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")This example passes the credentials as plain text for the sake of illustration.Please use environment variables/other secure ways of storing credentials when logging in!As of May 30, 2022, Google introducedsome changes to their APIthat now require users to have an App Password. Manokit supports logging in with your App Password. Just pass your App Password instead of your regular password, like this:frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="ccfv jels tttm hshe")By default, Manokit uses STARTTLS to encrypt the communication and make it more secure. If you would like to use SSL instead, simply disable STARTTLS during authentication and updating the port.frommanokitimportEmailemail=Email("smtp.gmail.com",465)email.login(username="manokit@gmail.com",password="manokit_is_cool",use_starttls=False,)Manokit does not support unencrypted communication over SMTP port 25.After you have finished with Manokit, you need to calllogout()function to close the SMTP session.frommanokitimportEmailemail=Email("smtp.gmail.com",465)email.login(username="manokit@gmail.com",password="manokit_is_cool",use_starttls=False,)# Your email stuffemail.logout()Adding recipientsTo add an email address to the list of recipients, simply call the appropriate function:frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("buddy@examplecorp.com")email.logout()For now, you can add recipients one at a time, so for each one you need to call theadd_recipientfunction separately.If you want to CC a person instead, replace theadd_recipientfunction withadd_cc:frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("boss@examplecorp.com")# This is importantemail.add_cc("buddy@examplecorp.com")email.logout()However, make sure to add at least one recipient, or else the email will not be sent.Same thing for BCC:frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("boss@examplecorp.com")email.add_bcc("spy@rivalcorp.com")email.logout()It is important to know that if you try to add an email address to either recipients, CC, or BCC when it already is added to one of them,these function will have no effect.frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("buddy@examplecorp.com")email.add_cc("buddy@examplecorp.com")print(len(email.rec))# Output: 1print(len(email.cc))# Output: 0email.logout()Composing an emailA simple email consists of a subject and a body. Both of these things are set by Manokit'sset_subjectandset_bodyfunctions, respectively.frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("buddy@examplecorp.com")email.set_subject("Manokit is kinda cool!")email.set_body("Hey, you heard about that library called Manokit? I tried it and it is nice ngl. Give it a try!")email.logout()The use of these functions is not compulsory, however. Manokit defaults the subject and the body to<no subject>and<no body>, respectively.Manokit encodes the body of an email astext/html, rather thantext/plain. This allows you to use HTML markup for styling and emphasis.Custom Email ValidationBy default, Manokit will validate user emails in certain cases (e.g. adding recipients, logging in, adding addresses to CC and BCC, etc) using a general-purpose regular expression.Specifically, the regular expression used is this one:^[-_+.\d\w]+@[-_+\d\w]+(?:\.{1}[\w]+)+$However, if you find this validation mechanism unsuitable for their needs, like if you need to limit the domain that can be used, you can easily override it by providing your own validation logic.The validator must be callable that accepts a single parameter of typestrand returns a value of typebool. Validator type:Callable[[str], bool]frommanokitimportEmaildefbetter_email_validator(addr:str)->bool:returnaddr.endswith("@our_company.com")email=Email("smtp.gmail.com",587)email.login(username="you@our_company.com",password="manokit_is_cool")email.set_custom_email_validator(better_email_validator)email.add_recipient("buddy@our_company.com")# This will passemail.add_bcc("spy@rival_corp.com")# This will raise an exceptionManokit also implements validation scopes. That means that, if you want to apply your custom validator only to certain parts, e.g. only to people who are BCC'd into the email, you can do it.frommanokitimportEmaildefcheck_who_is_in_bcc(addr:str)->bool:returnaddr.endswith("@our_company.com")email=Email("smtp.gmail.com",587)email.login(username="you@our_company.com",password="manokit_is_cool")email.set_custom_email_validator(check_who_is_in_bcc,scopes=["bcc"])email.add_recipient("client@clientperonal.org")# This will passemail.add_cc("clientswife@gmail.com")# This will also passemail.add_bcc("spy@rival_corp.com")# This will raise an exceptionAvailable scopes:all-- apply your validation rules to all addresses. This is the default option used by Manokitauthor-- apply your validation rules only to the sender's email. This validator will be applied duringlogin(), so the setter needs to be called before thatrecipients-- apply your validation rules only to recipients' addressescc-- apply your validation rules only to addresses that will be CC'd into the emailbcc-- apply your validation rules only to addresses that will be BCC'd into the emailAdding attachmentsSometimes we need to send an email with a file attached to it. To attach the file to your email, simply call theadd_attachmentfunction and provide a path to the file.frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("boss@examplecorp.com")email.add_attachment("./reports/quarterly_q3_q4.pdf")email.logout()Just as withadd_recipient,add_bccandadd_cc, theadd_attachmentfunction adds one file at a time.If an attachment has already been added, or if the size of the file being attach is 0, the function will have no effect.frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("boss@examplecorp.com")email.add_attachment("./reports/empty_report.pdf")print(len(email.attachments))# Output: 0email.logout()Attachment size limitBy default, Manokit limits the combined size of the attachments to 25 MB (can be adjusted during theInitialization).Manokit also maintains an internal counter of how much space is available for future attachments.frommanokitimportEmailemail=Email("smtp.gmail.com",587,filesize_limit=100)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("boss@examplecorp.com")email.add_attachment("./reports/40kb_report.txt")print(email.available_filesize)# Output: 60email.logout()If the attachment's size exceeds the limit, anAttachmentErrorwill be raised.Sending an emailTo send an email, just callsend()frommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool")email.add_recipient("buddy@examplecorp.com")email.add_cc("buddy@examplecorp.com")email.send()email.logout()This function can raise anEmailErrorif no recipients are defined or there was a problem while sending an email.Method chainingManokit's functions support method chainingfrommanokitimportEmailemail=Email("smtp.gmail.com",587)email.login(username="manokit@gmail.com",password="manokit_is_cool",).add_recipient("buddy@examplecorp.com").add_cc("buddy@examplecorp.com").send().logout()Thelogout()function, however, is considered a logical endpoint, and thus does not support method chaining. In other words, thelogout()function must be the last to be called.ExceptionsNotAValidEmailAddressErrorThis exception is raised when the email address fails validation.Functions that can raise it:login()add_recipient()add_cc()add_bcc()EmailErrorThis exception is raised when there is a problem with the email itself. For now this exception is only raised by thesend()function if there is no recipients or if there was a problem with sending an emailAttachmentErrorThis exception is raised when there is a problem with email's attachments. for now this exception is only raised by theadd_attachment()function if the path provided does not point to a file or the attachment's size is larger that the available space.ChangelogSee the full changeloghere.