SSL certificate error with Python sending email code - email

Im trying to use python to build an email sender.
Ive been getting an SSL certificate error, though I downloaded it.
Im also getting an SMTP error, which i think shouldn't be happening.
I've tried to fix this error but the solution I found was that of Mac and not windows.
The error:
with smtplib.SMTP_SSL( 'smtp.gmail.com' , 465, context=context) as smtp:
File "C:\Program Files\Inkscape\lib\python3.10\smtplib.py", line 1050, in __init__
SMTP.__init__(self, host, port, local_hostname, timeout,
File "C:\Program Files\Inkscape\lib\python3.10\smtplib.py", line 255, in __init__
(code, msg) = self.connect(host, port)
File "C:\Program Files\Inkscape\lib\python3.10\smtplib.py", line 341, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "C:\Program Files\Inkscape\lib\python3.10\smtplib.py", line 1057, in _get_socket
new_socket = self.context.wrap_socket(new_socket,
File "C:\Program Files\Inkscape\lib\python3.10\ssl.py", line 513, in wrap_socket
return self.sslsocket_class._create(
File "C:\Program Files\Inkscape\lib\python3.10\ssl.py", line 1071, in _create
self.do_handshake()
File "C:\Program Files\Inkscape\lib\python3.10\ssl.py", line 1342, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)
The code:
from email.message import EmailMessage
from emailApp import password
import ssl
try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
# Legacy Python that doesn't verify HTTPS certificates by default
pass
else:
# Handle target environment that doesn't support HTTPS verification
ssl._create_default_https_context = _create_unverified_https_context
import smtplib
email_sender = 'example2#mail.com'
email_password = password
email_receiver = 'example#gmail.com'
subject = "msg"
body = """
Hello
"""
em = EmailMessage()
em['From'] = email_sender
em['To'] = email_receiver
em['Subject'] = subject
em.set_content(body)
context = ssl.create_default_context()
context = ssl.create_default_context()
with smtplib.SMTP_SSL( 'smtp.gmail.com' , 465, context=context) as smtp:
smtp.login(email_sender, email_password)
smtp.sendmail(email_sender, email_receiver, em.as_string())

Related

SMTP email integration in cloud composer

I want to use SMTP email in GCP cloud composer. I have followed the GCP documentation and did the following -
Created a secret with my SMTP password (tested with secret name as airflow-variables-smtp-password & airflow-config-smtp-password)
Provided secret accessor role to my svc account
Modified email backend and all configs -
[email]
email_backend = airflow.utils.email.send_email_smtp
[smtp]
smtp_port = 587
smtp_user = ****
smtp_mail_from = ****
smtp_password_secret = smtp-password
smtp_host = smtp.office365.com
Changed secret backend -
[secrets]
backend = airflow.providers.google.cloud.secrets.secret_manager.CloudSecretManagerBackend
Below is my email dag which is subject to fail (tested with email operator as well) -
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
def print_hello():
pppp
return 'Hello Wolrd'
args = {
'owner': '***',
'depends_on_past': False,
'start_date': "2021-09-14",
'email_on_failure': True
}
with DAG(
dag_id='mail_testing',
default_args=args,
) as dag:
python_task = PythonOperator(
task_id='email_task',
python_callable=print_hello,
email_on_failure=True,
email= ['***'],
dag=dag
)
When running the dag, I am seeing it is looking for sendgrid to send the email.
[2021-09-29 17:42:20,958] {logging_mixin.py:104} WARNING - /opt/python3.8/lib/python3.8/site-packages/airflow/providers/sendgrid/utils/emailer.py:122 PendingDeprecationWarning: Fetching Sendgrid credentials from environment variables will be deprecated in a future release. Please set credentials using a connection instead.
[2021-09-29 17:42:21,081] {taskinstance.py:1503} ERROR - Task failed with exception
Traceback (most recent call last):
File "/opt/python3.8/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1158, in _run_raw_task
self._prepare_and_execute_task_with_callbacks(context, task)
File "/opt/python3.8/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1333, in _prepare_and_execute_task_with_callbacks
result = self._execute_task(context, task_copy)
File "/opt/python3.8/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1363, in _execute_task
result = task_copy.execute(context=context)
File "/opt/python3.8/lib/python3.8/site-packages/airflow/operators/email.py", line 79, in execute
send_email(
File "/opt/python3.8/lib/python3.8/site-packages/airflow/utils/email.py", line 55, in send_email
return backend(
File "/opt/python3.8/lib/python3.8/site-packages/airflow/providers/sendgrid/utils/emailer.py", line 122, in send_email
_post_sendgrid_mail(mail.get(), conn_id)
File "/opt/python3.8/lib/python3.8/site-packages/airflow/providers/sendgrid/utils/emailer.py", line 141, in _post_sendgrid_mail
response = sendgrid_client.client.mail.send.post(request_body=mail_data)
File "/opt/python3.8/lib/python3.8/site-packages/python_http_client/client.py", line 277, in http_request
self._make_request(opener, request, timeout=timeout)
File "/opt/python3.8/lib/python3.8/site-packages/python_http_client/client.py", line 184, in _make_request
raise exc
python_http_client.exceptions.UnauthorizedError: HTTP Error 401: Unauthorized
[2021-09-29 17:42:21,084] {taskinstance.py:1546} INFO - Marking task as UP_FOR_RETRY.
What am I doing wrong? Is there anything I am missing!
PendingDeprecationWarning: Fetching Sendgrid credentials from environment variables will be deprecated in a future release. Please set credentials using a connection instead.
These docs describe configuring Sendgrid credentials in a connection. I would follow them, as they include steps for troubleshooting.
The other possibility is that it's an issue with your Sendgrid credentials. You can test your sendGrid credentials are valid by sending a test-email via a curl request.

Not able to trigger DAG from Airflow API but its working from Curl command

I am trying to trigger DAG from Airflow API through python script.
DAG is triggering from curl command but its not working from API.
import requests
url ='http://localhost:8080/api/experimental/dags/document_validation/dag_runs'
myobj = {''}
x =requests.post(url, data=myobj, headers={"Content-Type": "application/json"})
print(x.text)
Error I am getting
File "run_dag_api.py", line 6, in <module>
  `x = requests.post(url, data = myobj)`
File "/…/lib/python3.7/site-packages/requests/api.py", line 119, in post
  `return request('post', url, data=data, json=json, **kwargs)`
File "/…/lib/python3.7/site-packages/requests/api.py", line 61, in request
  `return session.request(method=method, url=url, **kwargs)`
File "/…/lib/python3.7/site-packages/requests/sessions.py", line 530, in request
  `resp = self.send(prep, **send_kwargs)`
File "/…/lib/python3.7/site-packages/requests/sessions.py", line 643, in send
  `r = adapter.send(request, **kwargs)`
File "/…/lib/python3.7/site-packages/requests/adapters.py", line 498, in send
  `raise ConnectionError(err, request=request)`
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Long URL (including a key) causes unicode idna codec decoding error whilst using RedisChannelLayer in Django Channels

I've encountered a problem deploying Django Channels on Heroku, whilst using a RedisChannelLayer.
I get a UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long) during connection (full traceback below).
That seems to be a problem related to one of the labels in the host address being too long as shown in this python issue.
I printed some information out of my consumer, and also wrapped python's socket.getaddrinfo module to display host and connection information.
This related post has has the same problem connecting to shopify, not a redis instance, where they got around it by placing credentials into the request header. But I don't have control over channels_redis or asyncio.
Any clues?
Properties of the Django Channels Consumer:
.groups []
.channel_layer RedisChannelLayer(hosts=[{'address': ('h:alongkeycomprisingof65charsintotalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#ec2-18-202-152-61.eu-west-1.compute.amazonaws.com', '9759')}])
.channel_name specific.OSfTzyqY!pdvgHnaCxWiv
.room_name 8e3d3083-8bb1-4d85-89d3-4496d9b9e946
.room_group_name twined_8e3d3083-8bb1-4d85-89d3-4496d9b9e946
Full Traceback:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.6/site-packages/channels/sessions.py", line 183, in __call__
return await self.inner(receive, self.send)
File "/app/.heroku/python/lib/python3.6/site-packages/channels/middleware.py", line 41, in coroutine_call
await inner_instance(receive, send)
File "/app/.heroku/python/lib/python3.6/site-packages/channels/consumer.py", line 59, in __call__
[receive, self.channel_receive], self.dispatch
File "/app/.heroku/python/lib/python3.6/site-packages/channels/utils.py", line 51, in await_many_dispatch
await dispatch(result)
File "/app/.heroku/python/lib/python3.6/site-packages/channels/consumer.py", line 73, in dispatch
await handler(message)
File "/app/.heroku/python/lib/python3.6/site-packages/channels/generic/websocket.py", line 175, in websocket_connect
await self.connect()
File "/app/backend/pink/consumers.py", line 24, in connect
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
File "/app/.heroku/python/lib/python3.6/site-packages/channels_redis/core.py", line 589, in group_add
async with self.connection(self.consistent_hash(group)) as connection:
File "/app/.heroku/python/lib/python3.6/site-packages/channels_redis/core.py", line 835, in __aenter__
self.conn = await self.pool.pop()
File "/app/.heroku/python/lib/python3.6/site-packages/channels_redis/core.py", line 73, in pop
conns.append(await aioredis.create_redis(**self.host, loop=loop))
File "/app/.heroku/python/lib/python3.6/site-packages/aioredis/commands/__init__.py", line 175, in create_redis
loop=loop)
File "/app/.heroku/python/lib/python3.6/site-packages/aioredis/connection.py", line 113, in create_connection
timeout)
File "/app/.heroku/python/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/app/.heroku/python/lib/python3.6/site-packages/aioredis/stream.py", line 24, in open_connection
lambda: protocol, host, port, **kwds)
File "/app/.heroku/python/lib/python3.6/asyncio/base_events.py", line 750, in create_connection
infos = f1.result()
File "/app/.heroku/python/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "./backend/amy/asgi.py", line 69, in mygetaddrinfo
for res in socket._socket.getaddrinfo(host, port, family, type, proto, flags):
UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)
I've been able to work around by establishing my RedisChannelLayer using a dict of arguments to create_connection (as mentioned here, instead of providing a really long host name.
By manually parsing the password out of the REDIS_URL variable that heroku provides me, and rebuilding a host uri without it, I can add that password as a separate field to the create_connection dict, keeping the host string length below 64 characters.
I do this in my settings.py file which now looks like:
def parse_redis_url(url):
""" parses a redis url into component parts, stripping password from the host.
Long keys in the url result in parsing errors, since labels within a hostname cannot exceed 64 characters under
idna rules.
In that event, we remove the key/password so that it can be passed separately to the RedisChannelLayer.
Heroku REDIS_URL does not include the DB number, so we allow for a default value of '0'
"""
parsed = urlparse(url)
parts = parsed.netloc.split(':')
host = ':'.join(parts[0:-1])
port = parts[-1]
path = parsed.path.split('/')[1:]
db = int(path[0]) if len(path) >= 1 else 0
user, password = (None, None)
if '#' in host:
creds, host = host.split('#')
user, password = creds.split(':')
host = f'{user}#{host}'
return host, port, user, password, db
REDIS_URL = env('REDIS_URL', default='redis://localhost:6379')
REDIS_HOST, REDIS_PORT, REDIS_USER, REDIS_PASSWORD, REDIS_DB = parse_redis_url(REDIS_URL)
# DJANGO CHANNELS
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [{
'address': f'redis://{REDIS_HOST}:{REDIS_PORT}',
'db': REDIS_DB,
'password': REDIS_PASSWORD,
}],
},
},
}

Use signal handle to shut down flask-socketio server

I am using macOS Mojave and Python 3.7. In my work, I want to shut down flask-socketio server completely from the signal handler, which is defined as SignalHandler in my code. I noticed that, without the signal handler, the server can be shut down completely with Ctrl-C. However, the signal handler is necessary for my work. I searched online and couldn't find the solution to shut the server down in my case. For your information, I found solutions to shut the server down by "call flask-socketio stop from HTTP or SocketIO handler function", or "shut down a gevent (pywsgi) server gracefully".
The example code is given as below:
import os
import threading
import signal
import requests
from flask import Flask, send_from_directory
from flask_socketio import SocketIO, Namespace
import eventlet
class WebsiteCreator(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
app = Flask(__name__, template_folder="templates",
static_folder="templates/static")
app.config['SECRET_KEY'] = 'Secret!'
socketio = SocketIO(app, engineio_logger=True, logger=True)
# Create a URL route in our application for "/"
#app.route('/')
def test_page():
"""
This function loads the homepage
"""
return send_from_directory(
os.path.join(app.root_path, 'templates'),
"index1.html"
)
#app.route('/stop', methods=['POST'])
def shutdown_server():
"""
This function stops the flask-socketio server
"""
print("Received request to shut down the server.")
socketio.stop() #something wrong here, but don't know how to solve
return "The server has been shut down."
class MyCustomNamespace(Namespace):
def on_connect(self):
print("Client just connected")
def on_disconnect(self):
print("Client just left")
def on_messages(self, data):
print(f"\nReceived data from client: \n {data}\n")
return data
socketio.on_namespace(MyCustomNamespace('/channel_A'))
try:
eventlet.wsgi.server(
eventlet.wrap_ssl(eventlet.listen(("localhost", 8080)),
certfile='server.crt',
keyfile='server.key',
server_side=True), app)
except Exception as e:
print(f"Website is not established due to:\n{e}")
# Terminate code from shell
class SignalHandler(object):
def __init__(self):
pass
def __call__(self, signum, frame):
print("Shutting down the website.")
# Begin 'something' here to shut down the server...
shutdown_server = requests.post("https://localhost:8080/stop", data=None)
print(f"Shut down the server feedback: {shutdown_server}")
# 'Something' ends here
print("The website has been shut down.")
if __name__ == '__main__':
WebsiteCreator().start()
# If the following part is not included, the server can be shut down using Ctrl-C
handler = SignalHandler()
signal.signal(signal.SIGINT, handler)
In the code, I am running the flask-socketio server in a thread. I want to shut the server down by doing some actions in the SignalHandler.
Yet, when I exited the system with Ctrl-C, some exceptions raised:
^C
Shutting down the website.
(23066) accepted ('127.0.0.1', 49720)
Received request to shut down the server.
127.0.0.1 - - [22/Nov/2019 13:08:18] "POST /stop HTTP/1.1" 200 0 0.000365
wsgi exiting
Exception ignored in: <module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1308, in _shutdown
lock.acquire()
File "web_app.py", line 74, in __call__
shutdown_server = requests.post("https://localhost:8080/stop", data=None)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 116, in post
return request('post', url, data=data, json=json, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 60, in request
return session.request(method=method, url=url, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 646, in send
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/hubs/kqueue.py", line 105, in wait
readers.get(fileno, hub.noop).cb(fileno)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/greenthread.py", line 221, in main
result = function(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 818, in process_request
proto.__init__(conn_state, self)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 357, in __init__
self.handle()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 390, in handle
self.handle_one_request()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 419, in handle_one_request
self.raw_requestline = self._read_request_line()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 402, in _read_request_line
return self.rfile.readline(self.server.url_length_limit)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 589, in readinto
return self._sock.recv_into(b)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 241, in recv_into
return self._base_recv(nbytes, flags, into=True, buffer_=buffer)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 256, in _base_recv
read = self.read(nbytes, buffer_)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 176, in read
super(GreenSSLSocket, self).read, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 150, in _call_trampolining
return func(*a, **kw)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 926, in read
raise ValueError("Read on closed or unwrapped SSL socket.")
r = adapter.send(request, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 498, in send
ValueError: Read on closed or unwrapped SSL socket.
Removing descriptor: 8
142f38bdaaf34c7e8883e99a766fe310: Unexpected error "Read on closed or unwrapped SSL socket.", closing connection
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
Please give me some ideas! Thanks in advance.
This is what I use in my projects, works great using gevent. Make sure you start your server AFTER you init your signal. The signal should be identical, just minus the gevent part.
def shutdown():
print('Shutting down ...')
server.stop(timeout=60)
exit(signal.SIGTERM)
gevent.signal(signal.SIGTERM, shutdown)
gevent.signal(signal.SIGINT, shutdown) #CTRL C
server.serve_forever()

Couldn't connect to host server (odoo v11)

I was working on odoo, precisely in Website builder module while I was creating a website via the host IP address 192.168.1.2:9012, suddenly it crashes and shown me an Internal server error.
I tried to have a look at the log file and got this traceback,
2018-12-06 18:14:31,432 1 INFO ? odoo.sql_db: Connection to the database failed
2018-12-06 18:14:31,436 1 INFO ? werkzeug: 192.168.1.9 - - [06/Dec/2018 18:14:31] "GET /favicon.ico HTTP/1.1" 500 -
2018-12-06 18:14:31,441 1 ERROR ? werkzeug: Error on request:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/werkzeug/serving.py", line 205, in run_wsgi
execute(self.server.app)
File "/usr/lib/python3/dist-packages/werkzeug/serving.py", line 193, in execute
application_iter = app(environ, start_response)
File "/usr/lib/python3/dist-packages/odoo/service/server.py", line 250, in app
return self.app(e, s)
File "/usr/lib/python3/dist-packages/odoo/service/wsgi_server.py", line 166, in application
return application_unproxied(environ, start_response)
File "/usr/lib/python3/dist-packages/odoo/service/wsgi_server.py", line 154, in application_unproxied
result = handler(environ, start_response)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1318, in _call_
return self.dispatch(environ, start_response)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1292, in _call_
return self.app(environ, start_wrapped)
File "/usr/lib/python3/dist-packages/werkzeug/wsgi.py", line 599, in _call_
return self.app(environ, start_response)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1455, in dispatch
self.setup_db(httprequest)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1387, in setup_db
httprequest.session.db = db_monodb(httprequest)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1539, in db_monodb
dbs = db_list(True, httprequest)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 1506, in db_list
dbs = odoo.service.db.list_dbs(force)
File "/usr/lib/python3/dist-packages/odoo/service/db.py", line 369, in list_dbs
with closing(db.cursor()) as cr:
File "/usr/lib/python3/dist-packages/odoo/sql_db.py", line 634, in cursor
return Cursor(self.__pool, self.dbname, self.dsn, serialized=serialized)
File "/usr/lib/python3/dist-packages/odoo/sql_db.py", line 178, in _init_
self._cnx = pool.borrow(dsn)
File "/usr/lib/python3/dist-packages/odoo/sql_db.py", line 517, in _locked
return fun(self, *args, **kwargs)
File "/usr/lib/python3/dist-packages/odoo/sql_db.py", line 585, in borrow
**connection_info)
File "/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 164, in connect
conn = _connect(dsn, connection_factory=connection_factory, async=async)
psycopg2.OperationalError: could not connect to server: No route to host
Is the server running on host "172.17.0.4" and accepting
TCP/IP connections on port 5432 ?
I believe that's a network problem, I couldn't connect to the host server. do you have any idea about this please?
Thank you.
The error is from Odoo server because it cannot connect to the PostgreSQL database. First make sure your database service is running and available.
From your ip addresses I assume you are running database locally in some kind of virtualization environment like Docker. If you are not able to connect, please describe your environment in more detail. This will make it possible for stackoverflowers to help you.