Python3: IMAP -- cannot refer to tuples as elements - email

I am working on a script to automatically login to a gmail account and write the email attachments. I have working code, but I am currently trying to refactor into a cleaner layout. I am having trouble figuring out how to convert tuples into variables that can be returned and then passed as arguments into subsequent functions. Is this even possible within this type of solution?
The login and filter work, but I get the following error, having to do with the typ, email_selection item: NameError: name 'email_selection' is not defined
import email, getpass, imaplib, os, sys
from date_range import start_date, end_date
#enter_credentials
user_name = input('Enter your gmail username:\n')
password = getpass.getpass('Enter your password:\n')
imap_key = imaplib.IMAP4_SSL('imap.gmail.com',993)
#login_to_the_mailbox
def login_to_the_mailbox(imap_key, user_name, password):
typ, login_attempt = imap_key.login(user_name, password)
if typ != 'OK':
print ('Not able to login!')
else:
print ('Login successful!')
#filter_the_mailbox
def filter_the_mailbox(imap_key, start_date, end_date):
imap_key.select('Inbox')
typ, email_selection = imap_key.search(None, "(UNSEEN)", "(SENTSINCE {0})".format(start_date), "(SENTBEFORE {0})".format(end_date))
if typ != 'OK':
print ('Not able to filter mailbox.')
else:
print ('Mailbox filtered!')
return email_selection
#fetch_the_mail
def fetch_the_mail(imap_key, email_selection):
for msg_id in email_selection[0].split():
typ, message_parts = imap_key.fetch(msg_id, '(RFC822)')
if typ != 'OK':
print ('Error fetching mail.')
else:
print ('Mail fetched!')

Related

i'm unable to get list of all the users who joined channel through presence in elixir, phoenix

this is a quiz channel and after joining I want to get all the users who joined all the quizzes
quiz channel
def join("quiz:" <> id, _params, socket) do
presence = Nuton.Presence.list("quiz:" <> id)
if presence == %{} do
send(self(), {:after_join_quiz, id})
response = %{message: "you can now listen"}
{:ok, response, socket}
else
quiz = "quiz:#{id}"
%{^quiz => %{metas: metas}} = presence
if Enum.count(metas) > 1 do
{:error, %{reason: "Some other user already accepted the invitation"}}
else
send(self(), {:after_join_quiz, id})
response = %{message: "you can now listen"}
:ok = ChannelWatcher.monitor(:quiz, self(), {__MODULE__, :leave, [id]})
{:ok, response, socket}
end
end
end
def handle_info({:after_join_quiz, id}, socket) do
presence = Presence.list(socket)
if presence == %{} do
{:ok, _} =
Presence.track(socket, "quiz:" <> id, %{
user_name: socket.assigns.current_user.username,
user_id: socket.assigns.current_user.id,
quiz_id: id
})
{:noreply, socket}
else
{:ok, _} =
Presence.track(socket, "quiz:" <> id, %{
user_name: socket.assigns.current_user.username,
user_id: socket.assigns.current_user.id,
quiz_id: id
})
Core.Endpoint.broadcast(
"user:all",
"invitation:decline",
%{message: "Some other user already accepted the invitation"}
)
{:noreply, socket}
end
end
with specific quiz_id I can get all the user who joined the channel but with all I cant is there any issue in my code plz check if it is
Controller
quiz_users = Nuton.Presence.list("quiz:all")
You'd need to cycle through all of the channels, somehow, to get that information. I believe there was a PR to get this info, before, actually, so you can cycle through all.
What would be better: if you have the socket join 2 channels, like a "lobby" or "all" channel and then each individual channel. When you track, you can specify the string for the topic instead of only putting in the socket:
track(socket, "quiz:all", socket.assigns.user.id,%{})

Flask PyMongo find_one() return None even when data exists

I just started using MongoDb and I am stuck when using find_one(). The find() function works perfectly but None type is returned when using find_one(). I am stuck at this point. Below is the code that I am using.
#mongo.py
#app.route('/update_user/<emp_id>', methods=['GET', 'POST'])
def update_user(emp_id):
print("Employee ID:", emp_id)
output = list(emp.find_one({'emp_id': emp_id}))
print("Output:", output)
if request.method == 'POST':
if not request.form.get['emp_id'] or not request.form.get['first_name'] or not request.form.get['last_name'] \
or not request.form.get['dept_name'] or not request.form.get['gender'] or not request.form.get['dob'] \
or not request.form.get['salary'] or not request.form['country_code'] \
or not request.form.get['mobile_no']:
flash('Please enter all the fields', 'error')
else:
emp_id = int(request.form.get('emp_id'))
first_name = request.form.get('first_name')
last_name = request.form.get('last_name')
dept_name = request.form.get('dept_name')
gender = request.form.get('gender')
dob = request.form.get('dob')
salary = float(request.form.get('salary'))
country_code = int(request.form['country_code'])
mobile_no = int(request.form.get('mobile_no'))
emp.update_one({"emp_id": emp_id, "first_name": first_name, "last_name": last_name,
"dept_name": dept_name, "gender": gender, "dob": dob, "salary": salary,
"country_code": country_code, "mobile_no": mobile_no})
flash('Employee Updated')
return redirect('user.html')
return render_template('update_user.html', emp_id=emp_id, output=output)
It throws the below error:
File "D:\projects\EmpMgmtFlask\mongo.py", line 37, in update_user
output = list(emp.find_one({'emp_id': emp_id}))
TypeError: 'NoneType' object is not iterable
find_one() doesn't return a cursor; it returns a single dictionary; so you don't need to wrap it in a list function.
output = emp.find_one({'emp_id': emp_id})

PG::SyntaxError at /bookmarks - I'm unable to work out why the SQL query is wrong

When running my application using sinatra, I get the error message PG::SyntaxError at /bookmarks
ERROR: syntax error at or near "{" LINE 1: SELECT * FROM users WHERE id = {:id=>"5"} ^
It happens when I click the submit button on /users/new route which should then take me to index route /.
The backtrace provides the following information
/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/database_connection.rb in async_exec
#connection.exec(sql)
/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/database_connection.rb in query
#connection.exec(sql)
/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/user.rb in find
result = DatabaseConnection.query("SELECT * FROM users WHERE id = #{id}")
app.rb in block in <class:BookmarkManager>
#user = User.find(id: session[:user_id])
This is the database_connection file
require 'pg'
class DatabaseConnection
def self.setup(dbname)
#connection = PG.connect(dbname: dbname)
end
def self.connection
#connection
end
def self.query(sql)
#connection.exec(sql)
end
end
This is the user model
require_relative './database_connection'
require 'bcrypt'
class User
def self.create(email:, password:)
encypted_password = BCrypt::Password.create(password
)
result = DatabaseConnection.query("INSERT INTO users (email, password) VALUES('#{email}', '#{encypted_password}') RETURNING id, email;")
User.new(id: result[0]['id'], email: result[0]['email'])
end
attr_reader :id, :email
def initialize(id:, email:)
#id = id
#email = email
end
def self.find(id)
return nil unless id
result = DatabaseConnection.query("SELECT * FROM users WHERE id = #{id}")
User.new(
id: result[0]['id'],
email: result[0]['email'])
end
end
This is the controller
require 'sinatra/base'
require './lib/bookmark'
require './lib/user'
require './database_connection_setup.rb'
require 'uri'
require 'sinatra/flash'
require_relative './lib/tag'
require_relative './lib/bookmark_tag'
class BookmarkManager < Sinatra::Base
enable :sessions, :method_override
register Sinatra::Flash
get '/' do
"Bookmark Manager"
end
get '/bookmarks' do
#user = User.find(id: session[:user_id])
#bookmarks = Bookmark.all
erb :'bookmarks/index'
end
post '/bookmarks' do
flash[:notice] = "You must submit a valid URL" unless Bookmark.create(url: params[:url], title: params[:title])
redirect '/bookmarks'
end
get '/bookmarks/new' do
erb :'bookmarks/new'
end
delete '/bookmarks/:id' do
Bookmark.delete(id: params[:id])
redirect '/bookmarks'
end
patch '/bookmarks/:id' do
Bookmark.update(id: params[:id], title: params[:title], url: params[:url])
redirect('/bookmarks')
end
get '/bookmarks/:id/edit' do
#bookmark = Bookmark.find(id: params[:id])
erb :'bookmarks/edit'
end
get '/bookmarks/:id/comments/new' do
#bookmark_id = params[:id]
erb :'comments/new'
end
post '/bookmarks/:id/comments' do
Comment.create(text: params[:comment], bookmark_id: params[:id])
redirect '/bookmarks'
end
get '/bookmarks/:id/tags/new' do
#bookmark_id = params[:id]
erb :'/tags/new'
end
post '/bookmarks:id/tags' do
tag = Tag.create(content: params[:tag])
BookmarkTag.create(bookmark_id: params[:id], tag_id: tag.id)
redirect '/bookmarks'
end
get '/users/new' do
erb :'users/new'
end
post '/users' do
user = User.create(email: params[:email], password: params[:password])
session[:user_id] = user.id
redirect '/bookmarks'
end
run! if app_file == $0
end
self.find(id), in the user model, is where the potentially offending SQL query resides.
I've tried;
"SELECT * FROM users WHERE id = #{id}"
and "SELECT * FROM users WHERE id = '#{id}'"
Beyond that, I'm stumped. The query looks fine, but sinatra is having none of it.
Hopefully someone can help me resolve this.
Thanks, in advance.
You're call find with a hash argument:
User.find(id: session[:user_id])
but it is expecting just the id:
class User
...
def self.find(id)
...
end
...
end
Then you end up interpolating a hash into your SQL string which results in invalid HTML.
You should be saying:
#user = User.find(session[:user_id])
to pass in just the id that User.find expects.
You're also leaving yourself open to SQL injection issues because you're using unprotected string interpolation for your queries rather than placeholders.
Your query method should use exec_params instead of exec and it should take some extra parameters for the placeholder values:
class DatabaseConnection
def self.query(sql, *values)
#connection.exec_params(sql, values)
end
end
Then things that call query should use placeholders in the SQL and pass the values separately:
result = DatabaseConnection.query(%q(
INSERT INTO users (email, password)
VALUES($1, $2) RETURNING id, email
), email, encypted_password)
result = DatabaseConnection.query('SELECT * FROM users WHERE id = $1', id)
...

pg8000.core.ProgrammingError: 'could not determine data type of parameter $2'

I'm using pg.8000 (Postgres) and trying to run the following SELECT query
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
member_username
)
Where member.username is a String.
But I am getting the following error.
pg8000.core.ProgrammingError: ('ERROR', 'ERROR', '42P18', 'could not determine data type of parameter $2', 'postgres.c', '1350', 'exec_parse_message', '', '')
However, when I run same query using GUI tool, everything runs fine and I get the results. What is the problem?
You passed the parameter wrong, you should give a tuple, a list or a dictionary
Example with a tuple:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
(member_username,)
)
Example with a list:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
[member_username]
)
Example with a dictionary:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %(mname)s
""",
{'mname' : member_username}
)
http://initd.org/psycopg/docs/usage.html#query-parameters

Twisted (Scrapy) and Postgres

Im using Scrapy (aka Twisted) and also Postgres as a database.
After I while my connections seem to fill up and then my script is been stuck. I checked this with this query SELECT * FROM pg_stat_activity; and read that its caused because Postgres has no connection pool.
I read about txpostgres and PGBouncer, Bouncer regrettably isn't an option, what else can I do to avoid this problem?
So far I use the following pipeline:
import psycopg2
from twisted.enterprise import adbapi
import logging
from datetime import datetime
import scrapy
from scrapy.exceptions import DropItem
class PostgreSQLPipeline(object):
""" PostgreSQL pipeline class """
def __init__(self, dbpool):
self.logger = logging.getLogger(__name__)
self.dbpool = dbpool
#classmethod
def from_settings(cls, settings):
dbargs = dict(
host=settings['POSTGRESQL_HOST'],
database=settings['POSTGRESQL_DATABASE'],
user=settings['POSTGRESQL_USER'],
password=settings['POSTGRESQL_PASSWORD'],
)
dbpool = adbapi.ConnectionPool('psycopg2', **dbargs)
return cls(dbpool)
def process_item(self, item, spider):
d = self.dbpool.runInteraction(self._insert_item, item, spider)
d.addErrback(self._handle_error, item, spider)
d.addBoth(lambda _: item)
return d
def _insert_item(self, txn, item, spider):
"""Perform an insert or update."""
now = datetime.utcnow().replace(microsecond=0).isoformat(' ')
txn.execute(
"""
SELECT EXISTS(
SELECT 1
FROM expose
WHERE expose_id = %s
)
""", (
item['expose_id'],
)
)
ret = txn.fetchone()[0]
if ret:
self.logger.info("Item already in db: %r" % (item))
txn.execute(
"""
UPDATE expose
SET last_seen=%s, offline=0
WHERE expose_id=%s
""", (
now,
item['expose_id']
)
)
else:
self.logger.info("Item stored in db: %r" % (item))
txn.execute("""
INSERT INTO expose (
expose_id,
title
) VALUES (%s, %s)
""", (
item['expose_id'],
item['title']
)
)
# Write image info (path, original url, ...) to db, CONSTRAIN to expose.expose_id
for image in item['images']:
txn.execute(
"""
INSERT INTO image (
expose_id,
name
) VALUES (%s, %s)
""", (
item['expose_id'],
image['path'].replace('full/', '')
)
)
def _handle_error(self, failure, item, spider):
"""Handle occurred on db interaction."""
# do nothing, just log
self.logger.error(failure, failure.printTraceback())