19 julio 2006

Enviando un correo con INDY

Vamos a crear un procedimiento para mandar correos electrónicos utilizando el componente TIdSMTP de la paleta de componentes INDY CLIENTS.

El componente no hace falta ponerlo en el formulario, ya que lo creo en tiempo real dentro del procedimiento. Sólo hace falta añadir en el apartado USES de nuestro formulario lo siguiente:

uses
IdSMTP, IdMessage;

Vamos con el procedimiento que envía un mensaje de correo electrónico:

procedure EnviarMensaje( sUsuario, sClave, sHost, sAdjunto, sAsunto, sDestino, sMensaje: String );
var SMTP: TIdSMTP;
Mensaje: TIdMessage;
Adjunto: TIdAttachment;
begin
// Creamos el componente de conexión con el servidor
SMTP := TIdSMTP.Create( nil );
SMTP.Username := sUsuario;
SMTP.Password := sClave;
SMTP.Host := sHost;
SMTP.Port := 25;
SMTP.AuthenticationType := atLogin;

// Creamos el contenido del mensaje
Mensaje := TIdMessage.Create( nil );
Mensaje.Clear;
Mensaje.From.Name := sDestino;
Mensaje.From.Address := sDestino;
Mensaje.Subject := sAsunto;
Mensaje.Body.Text := sMensaje;
Mensaje.Recipients.Add;
Mensaje.Recipients.Items[0].Address := sDestino;

// Si hay que meter un archivo adjunto lo creamos y lo asignamos al mensaje
if sAdjunto <> '' then
begin
if FileExists( sAdjunto ) then
Adjunto := TIdAttachment.Create( Mensaje.MessageParts, sAdjunto );
end
else
Adjunto := nil;

// Conectamos con el servidor SMTP
try
SMTP.Connect;
except
raise Exception.Create( 'Error al conectar con el servidor.' );
end;

// Si ha conectado enviamos el mensaje y desconectamos
if SMTP.Connected then
begin
try
SMTP.Send( Mensaje );
except
raise Exception.Create( 'Error al enviar el mensaje.' );
end;

try
SMTP.Disconnect;
except
raise Exception.Create( 'Error al desconectar del servidor.' );
end;
end;

// Liberamos los objetos creados
if Adjunto <> nil then
FreeAndNil( Adjunto );

FreeAndNil( Mensaje );
FreeAndNil( SMTP );

Application.MessageBox( 'Mensaje enviado correctamente.',
'Fin de proceso',MB_ICONINFORMATION );
end;
Y este es un ejemplo de envío de mensajes:

EnviarMensaje( 'juanito33', 'djeuE21', 'smtp.terra.es',
'c:\documento.zip', 'Te envio mi documento',
'felipe8843@terra.es', 'Adjunto archivo: documento.zip' );

Con un poco de imaginación se puede hacer que muestre el estado de la conexión en la barra de estado e incluso una barra de progreso para ver cuanto queda por terminar de enviar.

Pruebas realizadas en Delphi 7.

17 julio 2006

Conectando a pelo con INTERBASE o FIREBIRD

Aunque Delphi contiene componentes para mostrar directamente datos de una tabla, en ocasiones nos obligan a mostrar el contenido de una base de datos en una página web o en una presentación multimedia con SDL, OPENGL ó DIRECTX. En este caso, los componentes de la pestaña DATA CONTROLS no nos sirven de nada. Nos los tenemos que currar a mano.

Voy a mostraros un ejemplo de conexión con una base de datos de INTERBASE o FIREBIRD mostrando el resultado directamente dentro de un componente ListView, aunque con unas modificaciones se puede lanzar el resultado a un archivo de texto, página web, XML o lo que sea.

Lo primero es conectar con la base de datos:

function ConectarBaseDatos( sBaseDatos: String ): TIBDatabase;
var DB: TIBDatabase;
begin  DB := TIBDatabase.Create( nil );
  DB.Name := 'IB';
  DB.DatabaseName := '127.0.0.1:' + sBaseDatos;
  DB.Params.Add( 'user_name=SYSDBA' );
  DB.Params.Add( 'password=masterkey' );
  DB.SQLDialect := 3;
  DB.LoginPrompt := False;
  try
   DB.Open;
  except
   raise Exception.Create( 'No puedo conectar con INTERBASE/FIREBIRD.' + #13 + #13 + 'Consulte con el administrador del programa.' );
  end;

  Result := DB;
end;

Si nos fijamos en el procedimiento, primero se crea en tiempo real un componente de conexión a bases de datos TIBDatabase. Después le decimos con que IP va a conectar (en principio en nuestra misma máquina) y la ruta de la base de datos que es la que se le pasa al procedimiento.

Más adelante le damos el usuario y password por defecto y desactivamos en Login. Finalmente contectamos con la base de datos controlando la excepción si casca.

Un ejemplo de conexión sería:

var DB: TIBDatabase;

DB := ConectarBaseDatos( 'c:\bases\bases.gdb' ); // PARA INTERBASE Ó
DB := ConectarBaseDatos( 'c:\bases\bases.fdb' ); // PARA FIREBIRD

if DB = nil then
  Exit;

Una vez conectados a la base de datos vamos a ver como listar los registros de una tabla dentro de un ListView:

procedure ListarTabla( DB: TIBDatabase; sTabla: String; Listado: TListView );
var Campos: TStringList;
  i: Integer;
  Consulta: TIBSQL;
  Transaccion: TIBTransaction;
begin
  if DB = nil then Exit;

  // Creamos un stringlist para meter los campos de la tabla
  Campos := TStringList.Create;
  DB.GetFieldNames( sTabla, Campos );

  // Creamos una transacción para la consulta
  Transaccion := TIBTransaction.Create( nil );
  Transaccion.DefaultDatabase := DB;

  // Creamos una consulta
  Consulta := TIBSQL.Create( nil );
  Consulta.Transaction := Transaccion;
  Consulta.SQL.Add( 'SELECT * FROM ' + sTabla );
  Transaccion.StartTransaction;
  try
   Consulta.ExecQuery;
  except
   Transaccion.Rollback;
   raise;
  end;

  // Creamos en el listview una columna por cada campo
  Listado.Columns.Clear;
  Listado.Columns.Add;
  Listado.Columns[0].Width := 0;
  for i := 0 to Campos.Count - 1 do
  begin
   Listado.Columns.Add;
   Listado.Columns[i+1].Caption := Campos[i];
   Listado.Columns[i+1].Width := 100;
  end;

  // Listamos los registros
  Listado.Clear;
  while not Consulta.Eof do
  begin
   Listado.Items.Add;

   for i := 0 to Campos.Count - 1 do
    Listado.Items[Listado.Items.Count-1].SubItems.Add( Consulta.FieldByName(
Campos[i] ).AsString );

   Consulta.Next;
  end;

  // Una vez hemos terminado liberamos los objetos creados
  FreeAndNil( Campos );
  FreeAndNil( Consulta );
  FreeAndNil( Transaccion );
end;

Por supuesto, todo este proceso se puede mejorar refactorizando código y dividiendo las partes más importantes en clases más pequeñas. Haciendo muchas pruebas con objetos TIBSQL y TIBQuery me he dado cuenta que para operaciones donde se requiere velocidad los objetos TIBSQL con mucho más rápidos que los TIBQuery, aunque estos últimos son mucho más completos.

Pruebas realizadas en Delphi 7

Publicidad