How do I send a link using the smtplib module? F string not working - smtplib

email user specific developer jobs at a given location
import requests # for api
import smtplib # for emails
import auth
class Jobs:
URL = "https://jobs.github.com/positions" # base url for API
def _jobs_api(self): # get json data (jobs)
location = input("Where would you like to become a developer? \U0001f607\n") # location parameter
description = input("What type of developer are you interested in becoming? \U0001f608\n") # search term
response = requests.get(Jobs.URL,
headers={"Accept": "application/json"},
params={"location": location, "description": description} # query params
)
data = response.json()
return data
def _job_links(self):
data = self._jobs_api()
if data:
for job in data:
links = job['url']
return links
else:
print(f"Sorry, I was not able to find any {self.description} jobs in {self.location}...")
def send_jobs(self): # email auth
links = self._job_links()
smpt_object = smtplib.SMTP('smtp.gmail.com', 587)
smpt_object.ehlo()
smpt_object.starttls()
# use own authentication data
email = auth.email()
password = auth.password()
smpt_object.login(email, password)
# next, send the message
from_address = email
to_address = email
subject = "Developer Jobs"
message = "Here are some jobs you are looking for: {}".format(links)
msg = "Subject: "+subject+"\n"+message
print("Check your email for an update! \U0001f601")
smpt_object.sendmail(from_address, to_address, msg)
smpt_object.quit()
user = Jobs()
user.send_jobs()
I'm trying to use the line Here are some jobs you are looking for: {}".format(links) (or an f string preferably) to send the links found from the API. But, when I check my email, it doesn't show the message with the links.

You can try to send a html structured mail in python to send the url you want.
See this post to find out

Related

Trying to add custom fields to envelope definition from docusign rails example

I got the embedded signing method I got from rails example on how to implement docusign embedded signing into your rails app.
I added a custom_fields object and added to the envelope object I created from the example
def embedded_signing
# base_url is the url of this application. Eg http://localhost:3000
base_url = request.base_url
user = HiringManager.find params[:hiring_manager_id]
# Fill in these constants
# Obtain an OAuth token from https://developers.hqtest.tst/oauth-token-generator
access_token = Token.access_token
# Obtain your accountId from demo.docusign.com -- the account id is shown in the drop down on the
# upper right corner of the screen by your picture or the default picture.
account_id = ENV["docusign_client_id"]
# Recipient Information:
signer_name = user.full_name
signer_email = user.email
base_path = 'http://demo.docusign.net/restapi'
client_user_id = user.id # Used to indicate that the signer will use an embedded
# Signing Ceremony. Represents the signer's userId within
# your application.
authentication_method = 'None' # How is this application authenticating
# the signer? See the `authenticationMethod' definition
file_name = 'agreement.pdf' # The document to be signed.
# Step 1. Create the envelope request definition
envelope_definition = DocuSign_eSign::EnvelopeDefinition.new
envelope_definition.email_subject = "Please sign this Newcraft Placement Agreement"
doc = DocuSign_eSign::Document.new({
:documentBase64 => Base64.encode64(File.binread(File.join('data', file_name))),
:name => "Agreement signed", :fileExtension => "pdf", :documentId => "1"})
# The order in the docs array determines the order in the envelope
envelope_definition.documents = [doc]
# create a signer recipient to sign the document, identified by name and email
# We're setting the parameters via the object creation
signer = DocuSign_eSign::Signer.new ({
:email => signer_email, :name => signer_name,
:clientUserId => client_user_id, :recipientId => 1
})
sign_here = DocuSign_eSign::SignHere.new ({
:documentId => '1', :pageNumber => '4',
:recipientId => '1', :tabLabel => 'SignHereTab',
:xPosition => '75', :yPosition => '70'
})
# Tabs are set per recipient / signer
tabs = DocuSign_eSign::Tabs.new({:signHereTabs => [sign_here]})
signer.tabs = tabs
# Add the recipients to the envelope object
recipients = DocuSign_eSign::Recipients.new({:signers => [signer]})
envelope_definition.recipients = recipients
# Add custom fields to the envelope object
custom_fields = DocuSign_eSign::CustomFieldV2.new({
:configuration_type => 'text', :required => 'true',
:name => 'date', :fieldId => '', :value => 'Todays date'
})
envelope_definition.custom_fields = custom_fields
# Request that the envelope be sent by setting |status| to "sent".
# To request that the envelope be created as a draft, set to "created"
envelope_definition.status = "sent"
# Step 2. Call DocuSign with the envelope definition to have the
# envelope created and sent
configuration = DocuSign_eSign::Configuration.new
configuration.host = base_path
api_client = DocuSign_eSign::ApiClient.new configuration
api_client.default_headers["Authorization"] = "Bearer " + access_token
envelopes_api = DocuSign_eSign::EnvelopesApi.new api_client
results = envelopes_api.create_envelope account_id, envelope_definition
envelope_id = results.envelope_id
# Step 3. create the recipient view request for the Signing Ceremony
view_request = DocuSign_eSign::RecipientViewRequest.new
# Set the url where you want the recipient to go once they are done signing
# should typically be a callback route somewhere in your app.
view_request.return_url = "https://juice.newcraft.io/edit-manager"
# How has your app authenticated the user? In addition to your app's
# authentication, you can include authenticate steps from DocuSign.
# Eg, SMS authentication
view_request.authentication_method = authentication_method
# Recipient information must match embedded recipient info
# we used to create the envelope.
view_request.email = signer_email
view_request.user_name = signer_name
view_request.client_user_id = client_user_id
# Step 4. call the CreateRecipientView API
results = envelopes_api.create_recipient_view account_id, envelope_id, view_request
user.signed_agreement = true
user.save
# Step 5. Redirect the user to the Signing Ceremony
# Don't use an iFrame!
# State can be stored/recovered using the framework's session or a
# query parameter on the returnUrl (see the makeRecipientViewRequest method)
render json: results
rescue DocuSign_eSign::ApiError => e
#error_msg = e.response_body
render json: #error_msg
end
I am finding it difficult understanding how to insert a custom field that user can manually fill on the pdf agreement document that is displayed for users signature. I also know I need to add the position the custom field tab will reside which the documentation does not really explain how to add to an envelop object you create from a method.
First, let's try to see if we understand your requirement. You want user to fill in some data on the envelope and then collect this data in your application after the envelope is complete, is that correct?
To do that, you don't need custom fields. You can easily to that with regular tabs. Text tabs are probably the simplest way to do so. You add a text tab to your envelope, similar to how you added a SignHere tab and the user would have to fill in the text/value. You can then get this information using other API calls.
Here is the API call to obtain the tab value:
https://developers.docusign.com/esign-rest-api/reference/Envelopes/EnvelopeRecipientTabs/
You basically do a GET /v2.1/accounts/{accountId}/envelopes/{envelopeId}/recipients/{recipientId}/tabs if you are using the v2 or V2.1 API (just replace 2.1 with 2)

Check if certain keywords available in users email using gmail api in ruby on rails

I am trying to check/filter through users inbox emails and check for keywords "offer" and "letter"
from calling messages on gmail api it returns the message id and threads which you can use to get the message contents that I have added to an array from my example below
def keyword_check
client = Signet::OAuth2::Client.new(access_token: session[:access_token])
service = Google::Apis::GmailV1::GmailService.new
service.authorization = client
messages = service.list_user_messages('me')
#messages_json = []
messages.messages.each do |m|
response = HTTParty.get("https://www.googleapis.com/gmail/v1/users/me/messages/#{m.id}?access_token=#{session[:access_token]}")
res = JSON.parse(response.body)
#messages_json << res
end
filter = HTTParty.get("https://www.googleapis.com/gmail/v1/users/me/messages?q=offer?access_token=#{session[:access_token]}")
mes = JSON.parse(filter.body)
render json: #messages_json.to_json
end
this returns all the messages in an array but I am finding it difficult filtering the array and checking for the particular keywords and returning both a boolean of true or false and the message itself alone in the array?
I think you should check whether the keywords are present in the response.body before adding them to the array:
def keyword_check
client = Signet::OAuth2::Client.new(access_token: session[:access_token])
service = Google::Apis::GmailV1::GmailService.new
service.authorization = client
messages = service.list_user_messages('me')
#messages_json = []
messages.messages.each do |m|
response = HTTParty.get("https://www.googleapis.com/gmail/v1/users/me/messages/#{m.id}?access_token=#{session[:access_token]}")
res = JSON.parse(response.body)
#messages_json << res if matches_keywords(response.body)
end
filter = HTTParty.get("https://www.googleapis.com/gmail/v1/users/me/messages?q=offer?access_token=#{session[:access_token]}")
mes = JSON.parse(filter.body)
render json: #messages_json.to_json
end
def matches_keywords content
return true if content.include?('offer')
return true if content.include?('letter')
return false
end
Edit: Be aware that the body probably contains all the HTML formatting, css code etcetera... suppose for instance that there's a CSS rule with 'letter-spacing', the new function will always return true, so please check whether you are able to get the TEXT content instead. For this, have a look at the documentation for the Gmail API.
Another approach could be to use Kaminara (or equivalent) to really dive into the HTML structure, and only check the part that holds the actual text ( or some specific or something)

Scanning phone number for format to send SMS messages

I have code for scanning phone numbers to put into the correct format and then have the SMS sent to the phone number. Although, I don't know how to apply this the "best" way.
In my create method I have:
if #order.phone_number.present?
account_sid = '1234567890'
auth_token = '1234567890'
client = Twilio::REST::Client.new(account_sid, auth_token)
message = client.messages.create(
from: '+12017541209',
to: '+120188854064',
body: "You received Order from #{#order.listing.name} - View it here: localhost.com/order/#{#order.order_token}/order_confirmation" )
end
I then have this code for scanning:
def clean_number
number = self.phone_number.scan(/\d+/).join
number[0] == "1" ? number[0] = '' : number
number unless number.length != 10
end
The format I need is 11231234567
Whether the text_input is:
1-123-123-1234
123-123-1234
+1(123)-123-1234
etc.
Now, the SMS works but I haven't applied the clean_number method yet. Should i be putting this in my model, and then call it in the controller, or have it in the private within the controller?

Have to add a simple condition in Rails

I have to setup my rails project to send a confirmation SMS to new users. I have a table phone_calling_codes which has a column sms_enable_flag. In my DB this field has to be checked or not, so it's boolean.
I use Twilio to send SMS but I want to add a condition to send SMS only to the numbers where this sms_enable_flag is checked.
I also use phonelib to parse the number and take the country code from it.
def perform(phone_number, confirmation_code)
logger.info("Job started sending confirmation code")
overrideToPhone = [ "development","upgrade"].include? Rails.env
deliverSMS = !([ "development", "upgrade"].include? Rails.env)
phone=''
if overrideToPhone
e164Prefix = '+'
phone_number = e164Prefix + "17782002024"
else
phone = Phonelib.parse( phone_number)
phone_number = phone.e164
end
sms=phone_calling_codes.find_by calling_code: phone.country_code
if sms
if sms.sms_enabled_flag
from_phone_number = Rails.application.secrets.twilio_number
body = "Valorbit.com - your phone verification code is: #{confirmation_code}"
logger.info("From #{from_phone_number} to #{phone_number} : #{body}")
twilio_client.messages.create(
to: phone_number ,
from: from_phone_number ,
body: body
) if deliverSMS
logger.info("Sent sms to #{phone_number}") if deliverSMS
else
logger.info("SMS is not enabled for #{phone_number}")
end
end
end
Please help me to this. I am a beginner to OOP and I want to understand if it is ok how I have thought.
Thanks! :D
change line
sms=phone_calling_codes.find_by calling_code: phone.country_code
to
sms=PhoneCallingCode.find_by calling_code: phone.country_code
PhoneCallingCode is the model name present in /app/models folder
Below is the query to find data from model:
ModelName.find_by column_name: parameter

How do I pass unique_args to the SendGrid::TemplateMailer API from Ruby on Rails

I've been implementing the sendgrid-ruby gem to send email via SendGrid. I'm using templates exclusively for my messages to send. I've got everything working on the outbound side using the TemplateMailer implementation.
This is the code:
unique_args = {unique_args: {MyAuditNumber: "9999999"}}
# Create a sendgid recipient list
recipients = []
recipient = SendGrid::Recipient.new(to_email)
merge_vars.each do |mv|
Rails.logger.debug(mv)
recipient.add_substitution('*|' + mv["name"] + '|*', mv["content"])
end
recipients << recipient
# Create a sendgrid template
template = SendGrid::Template.new(template_id)
# Create a client
client = SendGrid::Client.new(api_key: Rails.configuration.sendgridkey)
mail_defaults = {
from: from_email,
from_name: from_name,
to: to_email,
to_name: to_name,
bcc: bcc,
html: ' ',
text: ' ',
subject: subject
}
mailer = SendGrid::TemplateMailer.new(client, template, recipients)
# send it
lres = mailer.mail(mail_defaults)
The last thing I want to do is to add a unique identifier to each message that I send.
I've read both the SendGrid documentation as well as several questions and other articles (
how to get response of email sent using sendgrid in rails app to save in database
http://thepugautomatic.com/2012/08/sendgrid-metadata-and-rails/
https://sendgrid.com/docs/Integrate/Code_Examples/SMTP_API_Header_Examples/ruby.html
)
I can tell that I need to add unique_args to the smtp API. But what I can't figure out is how to pass that into the SendGrid routines.
I've tried things like:
recipient.add_to_smtpapi( unique_args )
and
recipient.add_to_smtpapi( unique_args.to_json )
and
mail_defaults = {
smtpapi: unique_args,
from: from_email,
...
and
mail_defaults = {
smtpapi: unique_args.to_json,
from: from_email,
...
These attempts generally result in an error message like:
undefined method `add_filter' for "{\"unique_args\":{\"MyAuditNumber\":\"9999999\"}}":String
Does anyone know how to pass unique_args when using the TemplateMailer?
Based on gem documentation, what you should do is the following:
header = Smtpapi::Header.new
header.add_unique_arg("MyAuditNumber", "9999999")
mail_defaults = {
smtpapi: header
...

Resources