Envio de mails con formato html desde Python

Python es un lenguaje de programación muy potente y sencillo de aprender. Ademas, cuenta con una serie de librerías y módulos con funciones ya implementadas para hacer determinadas acciones comunes. Entre ellas, una que yo suelo utilizar, es la del envío de reportes por mail cuando finalizan mis scripts. Lo interesante es que con un formateo sencillo permite el envío de mensajes con el cuerpo en html, dándoles un mejor aspecto en nuestro gestor de correo.

Se deben importar dos módulos para poder realizar el envío de mails: smtplib y email.mime.text. El primero se encargará de la gestión de la conexión con el servidor de correo, mientras que el segundo servirá para dar la codificación correcta e incluirlo como texto MIME en el cuerpo del mensaje. 
Lo que yo creo es una función a la que le paso el cuerpo del mensaje y se encarga de empaquetarlo y enviarlo. A continuación muestro el ejemplo:
 def sendmail(body):  
smtpserver = 'smtp.dominio.com'
sender='sender@dominio.com'
sysadmin1='receiver1@dominio.com'
sysadmin2='receiver2@dominio.com'
receiver = [ sysadmin1 , sysadmin2 ]
header='''


Envio de mail formateado en HTML


h2 {font-size:14px;margin: 2px;}
h3 {font-size:12px;margin: 2px;}
p {font-size:10px; margin: 2px;}
td {border: 1px outset}


'''
footer=''
msgbdy = open(body, 'rb')
msg = MIMEText(header+msgbdy.read()+footer, 'html')
msgbdy.close()
msg['Subject'] = 'Asunto del mensaje'
msg['From'] = sender
msg['To'] = sysadmin1
msg['CC'] = sysadmin2
correo = smtplib.SMTP(smtpserver)
correo.sendmail(sender, receiver, msg.as_string())
correo.quit()
El código creo que no es muy complicado de entender, pero básicamente crearemos tres variables que concatenaremos con la cabecera, el cuerpo y el cierre del código html. Esto se lo pasaremos a la función MIMEText con un segundo parámetro, ‘html’ que especifica el Content-Type y lo pondremos en la variable msg como cuerpo de mensaje. A continuación se realiza la conexión con el servidor y se envía el mail.

A la funcion le paso como parámetro el nombre del fichero de log, que posteriormente se codificará como un objeto MIME.

En el fichero de log, en lugar de introducirle “retornos de carro”, introduzco etiquetas del tipo

,

,
e incluso estilos para modificar el formato de la salida.

SNMP y Trabajo con MIBs

Muchas veces debemos monitorizar elementos que disponen del protocolo SNMP. Normalmente es fácil encontrar el fichero de MIB del dispositivo que queremos monitorizar, ya sea en a través del fabricante o a través de webs de terceros como oidview. Una vez tenemos el fichero de la MIB, ¿que hacemos?¿Como podemos obtener el OID de un nodo en particular?

Como para todo, existirán múltiples formas de trabajar con este fichero, pero para los usuarios de Linux tenemos disponible el paquete “snmp” con un grupo de herramientas que nos servirán para nuestro propósito. Lo primero que deberemos hacer es instalar dicho paquete, si no lo hemos hecho ya antes, con un simple “sudo apt-get install snmp“. Una vez instalado tendremos disponibles comandos como snmpwalk, snmpget o snmptranslate.
En el siguiente ejemplo veremos como obtener el valor de algunas variables que nos pueden interesar para monitorizar un SAI con un adaptador CS121. Con dicho módulo venia su correspondiente CD de utilidades donde podíamos encontrar la MIB del producto, en concreto la RFC1628cs121.MIB. 
Nos podríamos ver tentados por visualizar dicho fichero, pero la sintaxis que utiliza (ASN1) no es la mas amigable para su lectura. 
La herramienta snmptranslate nos sirve para interpretar dicho fichero MIB. A primera vista podríamos analizar el arbol de la mib para evaluar que variables nos pueden interesar en la monitorización, para ello ejecutaremos el siguiente comando, especificando que carge el fichero de MIB del módulo:

julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -Tp 
+–iso(1)
   |
   +–org(3)
      |
      +–dod(6)
         |
         +–internet(1)
            |
            +–mgmt(2)
               |
               +–mib-2(1)
                  |
                  +–upsMIB(33)
                     |
                     +–upsObjects(1)
                     |  |
                     |  +–upsIdent(1)
                     |  |  |
                     |  |  +–upsIdentManufacturer(1)
                     |  |  |
                     |  |  +–upsIdentModel(2)
                     |  |  |
                     |  |  +–upsIdentUPSSoftwareVersion(3)
                     |  |  |
                     |  |  +–upsIdentAgentSoftwareVersion(4)
                     |  |  |
                     |  |  +–upsIdentName(5)
                     |  |  |
                     |  |  +–upsIdentAttachedDevices(6)
                     |  |
                     |  +–upsBattery(2)
                     |  |  |
                     |  |  +– -R– EnumVal   upsBatteryStatus(1)
                     |  |  |        Values: unknown(1), batteryNormal(2), batteryLow(3), batteryDepleted(4)
Si en la herramienta de monitorización podemos cargar el fichero de MIB, con interrogar al dispositivo con el nombre del nodo que nos interesa será suficiente (mas adelante explicaré algún ejemplo). En cambio, muchas herramientas de monitorización no permiten la carga del fichero de MIB y le debemos especificar el OID que queremos interrogar. El árbol de OIDs de la MIB lo podemos ver de la siguiente forma:
julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -To
.1.3
.1.3.6
.1.3.6.1
.1.3.6.1.2
.1.3.6.1.2.1
.1.3.6.1.2.1.33
.1.3.6.1.2.1.33.1
.1.3.6.1.2.1.33.1.1
.1.3.6.1.2.1.33.1.1.1
.1.3.6.1.2.1.33.1.1.2
.1.3.6.1.2.1.33.1.1.3
.1.3.6.1.2.1.33.1.1.4
.1.3.6.1.2.1.33.1.1.5
.1.3.6.1.2.1.33.1.1.6
.1.3.6.1.2.1.33.1.2
.1.3.6.1.2.1.33.1.2.1
.1.3.6.1.2.1.33.1.2.2
.1.3.6.1.2.1.33.1.2.3
.1.3.6.1.2.1.33.1.2.4
.1.3.6.1.2.1.33.1.2.5
.1.3.6.1.2.1.33.1.2.6
.1.3.6.1.2.1.33.1.2.7
.1.3.6.1.2.1.33.1.3
.1.3.6.1.2.1.33.1.3.1
.1.3.6.1.2.1.33.1.3.2
.1.3.6.1.2.1.33.1.3.3
.1.3.6.1.2.1.33.1.3.3.1
.1.3.6.1.2.1.33.1.3.3.1.1
.1.3.6.1.2.1.33.1.3.3.1.2
.1.3.6.1.2.1.33.1.3.3.1.3
.1.3.6.1.2.1.33.1.3.3.1.4
.1.3.6.1.2.1.33.1.3.3.1.5
El problema ahora es que no sabemos cual es la correspondencia entre el OID y el nodo que evaluamos. Esto se soluciona pasando como parámetro en el snmptranslate la opción -Tz, que nos devolverá la forma numérica y etiqueta de todos los objetos:
julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -Tz
“org” “1.3”
“dod” “1.3.6”
“internet” “1.3.6.1”
“mgmt” “1.3.6.1.2”
“mib-2” “1.3.6.1.2.1”
“upsMIB” “1.3.6.1.2.1.33”
“upsObjects” “1.3.6.1.2.1.33.1”
“upsIdent” “1.3.6.1.2.1.33.1.1”
“upsIdentManufacturer” “1.3.6.1.2.1.33.1.1.1”
“upsIdentModel” “1.3.6.1.2.1.33.1.1.2”
“upsIdentUPSSoftwareVersion” “1.3.6.1.2.1.33.1.1.3”
“upsIdentAgentSoftwareVersion” “1.3.6.1.2.1.33.1.1.4”
“upsIdentName” “1.3.6.1.2.1.33.1.1.5”
“upsIdentAttachedDevices” “1.3.6.1.2.1.33.1.1.6”
“upsBattery” “1.3.6.1.2.1.33.1.2”
“upsBatteryStatus” “1.3.6.1.2.1.33.1.2.1”
“upsSecondsOnBattery” “1.3.6.1.2.1.33.1.2.2”
“upsEstimatedMinutesRemaining” “1.3.6.1.2.1.33.1.2.3”
“upsEstimatedChargeRemaining” “1.3.6.1.2.1.33.1.2.4”
“upsBatteryVoltage” “1.3.6.1.2.1.33.1.2.5”
“upsBatteryCurrent” “1.3.6.1.2.1.33.1.2.6”
“upsBatteryTemperature” “1.3.6.1.2.1.33.1.2.7”
“upsInput” “1.3.6.1.2.1.33.1.3”
“upsInputLineBads” “1.3.6.1.2.1.33.1.3.1”
“upsInputNumLines” “1.3.6.1.2.1.33.1.3.2”
“upsInputTable” “1.3.6.1.2.1.33.1.3.3”
“upsInputEntry” “1.3.6.1.2.1.33.1.3.3.1”
“upsInputLineIndex” “1.3.6.1.2.1.33.1.3.3.1.1”
“upsInputFrequency” “1.3.6.1.2.1.33.1.3.3.1.2”
“upsInputVoltage” “1.3.6.1.2.1.33.1.3.3.1.3”
“upsInputCurrent” “1.3.6.1.2.1.33.1.3.3.1.4”
“upsInputTruePower” “1.3.6.1.2.1.33.1.3.3.1.5”

Para obtener mas información de un nodo en concreto primero deberíamos obtener la forma mas completa:

julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -Onf -IR upsInputTruePower
.iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsInput.upsInputTable.upsInputEntry.upsInputTruePower

Ya ejecutando el snmptranslate con el OID completo obtendremos mas información del nodo, con una descripción de la variable, las unidades, la  sintaxis, etc.

julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -Td -OS .iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsInput.upsInputTable.upsInputEntry.upsInputTruePower
UPS-MIB::upsInputTruePower
upsInputTruePower OBJECT-TYPE
  — FROM UPS-MIB
  — TEXTUAL CONVENTION NonNegativeInteger
  SYNTAX INTEGER (0..2147483647) 
  DISPLAY-HINT “d”
  UNITS “Watts”
  MAX-ACCESS read-only
  STATUS current
  DESCRIPTION “The magnitude of the present input true power.”
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) upsMIB(33) upsObjects(1) upsInput(3) upsInputTable(3) upsInputEntry(1) 5 }

Para obtener el OID numérico que utilizaremos en la herramienta de monitorización para este nodo ejecutaremos la siguiente consulta:

julian@ubuntu:$ snmptranslate -m “/tmp/RFC1628cs121.MIB” -On UPS-MIB::upsInputTruePower
.1.3.6.1.2.1.33.1.3.3.1.5
Con estos datos ya podemos montar nuestro sistema de monitorización, evaluando únicamente las variables que nos interesen. 
También tendremos dos utilizades que nos permitirán obtener los valores directamente desde el módulo. El snmpwalk hará un recorrido por las ramas del árbol desde el nodo que le especifiquemos mientras que el snmpget nos devolverá el valor específico de un nodo. En ambos métodos podemos especificar el fichero de MIB que queremos utilizar o especificar el OID en formato numérico. Veamos varios ejemplos:
julian@ubuntu:$ snmpget -Os -c comunidad -m “./RFC1628cs121.MIB” -v 1 DireccionIP upsOutputPower.1
upsOutputPower.1 = INTEGER: 700 Watts

julian@ubuntu:$ snmpget -Os -c comunidad -v 1 DireccionIP 1.3.6.1.2.1.33.1.4.4.1.4.1
mib-2.33.1.4.4.1.4.1 = INTEGER: 700

julian@ubuntu:$  snmpwalk -Os -c comunidad -m “./RFC1628cs121.MIB” -v 1 DireccionIP upsInputEntry
upsInputLineIndex.1 = INTEGER: 1
upsInputFrequency.1 = INTEGER: 500 0.1 Hertz
upsInputVoltage.1 = INTEGER: 230 RMS Volts
upsInputCurrent.1 = INTEGER: 0 0.1 RMS Amp
upsInputTruePower.1 = INTEGER: 0 Watts

julian@ubuntu:$ snmptranslate -m “./RFC1628cs121.MIB” -On UPS-MIB::upsInputEntry
.1.3.6.1.2.1.33.1.3.3.1
julian@ubuntu:$  snmpwalk -Os -c comunidad -v 1 DireccionIP .1.3.6.1.2.1.33.1.3.3.1
mib-2.33.1.3.3.1.1.1 = INTEGER: 1
mib-2.33.1.3.3.1.2.1 = INTEGER: 500
mib-2.33.1.3.3.1.3.1 = INTEGER: 230
mib-2.33.1.3.3.1.4.1 = INTEGER: 0
mib-2.33.1.3.3.1.5.1 = INTEGER: 0
Se puede encontrar mas información en los siguientes enlaces:

Uso de proxy en Linux

Uno de los problemas que nos encontramos al utilizar máquinas con Linux en entornos corporativos es la restricción de acceso a Internet. Muchas compañías disponen de un proxy de navegación que limita y controla donde pueden acceder los usuarios. En Linux disponemos diferentes formas de configurarlo, muchas veces no es trivial y dependiendo de si el proxy requiere autenticación o no, puede llevar mas de un quebradero de cabeza.

A continuación comentaré los diferentes casos que me he ido encontrando:
  • Uso del proxy desde la línea de comandos:
    • En la línea de comandos hay que configurar las variables de entorno que se utiliza para definir el proxy:
export http_proxy=”http://X.X.X.X:8080″
export https_proxy=”http://X.X.X.X:8080″
export ftp_proxy=”http://X.X.X.X:8080″
    • Para hacer el cambio permanente habría que editar el fichero del perfil para cargarlo al iniciar la shell (.bashrc para bash)
    • Si el proxy requiere autenticación, se puede especificar el usuario o el usuario y password de la siguiente manera:
    • Si no se configura el usuario y password se puede pasar como parámetro del wget, por ejemplo:
julian@ubuntu:~$ wget –proxy-user=usuario –proxy-password=password http://wwww.blabla.com/index.html
  • Uso del proxy para el gestor de paquetes de Ubuntu (apt, synaptic, software center):
  • Uso del proxy para el gestor de paquetes de Red Hat (y derivados):
    • Añadir en el fichero de configuración de yum los parámetros del proxy (/etc/yum.conf):

      proxy=http://X.X.X.X:8080 proxy_username=usuario proxy_password=password
  • Uso del proxy en el escritorio de ubuntu:
    • Desde la llegada de Unity ha cambiado un poco la configuración del proxy. Se configura en “System Settings” y ahí en Network. En el panel de la izquierda aparece la opción de configurar el proxy. Ahí para cada protocolo se debe especificar el servidor y el puerto a utilizar. El problema viene a la hora de utilizar autenticación, para eso deberemos configurarlo mediante el dconf-editor. Si no lo tenemos instalado se deberá instalar el paquete dconf-tools (sudo apt-get install dconf-tools).
Una vez abierto el dconf-editor iremos a la rama system->proxy. En esa rama general podremos configurar las excepciones para las que no utilizar el proxy. En la rama system->proxy->http podremos configurar el usuario y password de nuestro proxy:

Nota: En caso de que el password contenga algún carácter especial como una @ se deberá sustituir por el caracter ASCII en los ficheros de configuración (a excepción del de Yum, que se puede escribir sin modificaciones). Por ejemplo:
p@ssword pasaría a ser p%40ssword