Sending email in FreeBSD with Gmail

When I moved my mail functionality (gmail) from my FreeBSD-server to Google Apps I was left with no way to send email from my server (sendmail disabled and gmail removed) from shell. I have no longer the need to recieve email from my server, thanks to Google! However, I needed to send emails from my server to report server status and report software/hardware errors.

This is how I solved the problem on my FreeBSD 7.0 server.

1. Freebsd has a guide for setting up send only with ssmtp. First you should install ssmtp.

cd /usr/ports/mail/ssmtp/ && make install clean

2. Then you need to configure ssmtp for Gmail. Create this file in /usr/local/etc/ssmtp/ssmtp.conf. Replace email and password with your Gmail-account settings.

root=youremail@gmail.com
mailhub=smtp.gmail.com:587
AuthUser=youremail@gmail.com
AuthPass=yourpassword
UseSTARTTLS=YES

3. Test ssmtp. First you have to create a textfile with the message that you are going to send. Copy the text between the lines below.

Save the text to ”testmessage.txt”.
————————–
To: youremail@gmail.com
From: youremail@gmail.com
Subject: Testmessage

This is a test
--------------------------

Then run this command to send the testmessage.

ssmtp -v youremail@gmail.com < testmessage.txt

You should see the following output:

[<-] 220 mx.google.com ESMTP 14sm2982172ewy.10
[->] EHLO mysql
[<-] 250 PIPELINING
[->] STARTTLS
[<-] 220 2.0.0 Ready to start TLS
[->] EHLO servername
[<-] 250 PIPELINING
[->] AUTH LOGIN
[<-] 334 VXNlcm5hbWU6
[->] bWFyY3VzLm55YkBnbWFpbC5jb20=
[<-] 334 UGFzc3dvcmQ6
[<-] 235 2.7.0 Accepted
[->] MAIL FROM:
[<-] 250 2.1.0 OK 14sm2982172ewy.10
[->] RCPT TO:
[<-] 250 2.1.5 OK 14sm2982172ewy.10
[->] DATA
[<-] 354 Go ahead 14sm2982172ewy.10
[->] Received: by Servername (sSMTP sendmail emulation); Tue, 09 Mar 2010 12:53:14 +0100
[->] From: "Username"
[->] Date: Tue, 09 Mar 2010 12:53:14 +0100
[->] To: youremail@gmail.com
[->] Subject: Testmessage
[->]
[->] This is a test
[->] .
[<-] 250 2.0.0 OK 1268135596 14sm2982172ewy.10
[->] QUIT
[<-] 221 2.0.0 closing connection 14sm2982172ewy.10

If everything seems ok you should now have a fresh email in your Gmail account. Check it out! If not, then you should probably check your ssmtp.conf file and verify that you can connect to smtp.google.com

4. Last, replace sendmail with ssmtp. This makes ssmtp the default mailer for your system.

mv /usr/sbin/sendmail /usr/sbin/sendmail.org
ln -s /usr/local/sbin/ssmtp /usr/sbin/sendmail

5. Check that mail is working.

mail -v -s "TestSubject" youremail@gmail.com
Testing and
.

Output:
[<-] 220 mx.google.com ESMTP 16sm3004137ewy.7
[->] EHLO mysql
[<-] 250 PIPELINING
[->] STARTTLS
[<-] 220 2.0.0 Ready to start TLS
[->] EHLO servername
[<-] 250 PIPELINING
[->] AUTH LOGIN
[<-] 334 VXNlcm5hbWU6
[->] bWFyY3VzLm55YkBnbWFpbC5jb20=
[<-] 334 UGFzc3dvcmQ6
[<-] 235 2.7.0 Accepted
[->] MAIL FROM:
[<-] 250 2.1.0 OK 16sm3004137ewy.7
[->] RCPT TO:
[<-] 250 2.1.5 OK 16sm3004137ewy.7
[->] DATA
[<-] 354 Go ahead 16sm3004137ewy.7
[->] Received: by mysql (sSMTP sendmail emulation); Tue, 09 Mar 2010 13:11:41 +0100
[->] From: "Username"
[->] Date: Tue, 09 Mar 2010 13:11:41 +0100
[->] To: youremail@gmail.com
[->] Subject: TestSubject
[->]
[->] testing
[->] .
[<-] 250 2.0.0 OK 1268136703 16sm3004137ewy.7
[->] QUIT
[<-] 221 2.0.0 closing connection 16sm3004137ewy.7

6. Check the log file.

cat /var/log/maillog

Output:
SMTP[755]: Creating SSL connection to host
sSMTP[755]: SSL connection using RC4-MD5
sSMTP[755]: Sent mail for username@servername(221 2.0.0 closing connection 14sm3068161ewy.2) uid=0 username=username outbytes=696
sSMTP[1234]: Creating SSL connection to host
sSMTP[1234]: SSL connection using RC4-MD5
sSMTP[1234]: Sent mail for username@servername (221 2.0.0 closing connection 16sm3004137ewy.7) uid=0 username=username outbytes=349

Summary
This worked for me straight out of the box. I didn't need to make any changes to make it work. I hope it works for you as well!

Bygga egen spårsläde / spårdragare för längdåkning

Mitt senaste projekt var att tillverka en hemmagjord spårsläde för klassisk längdåkning som man kan dra efter en vanlig skoter. Det är perfekt att ha en egen spårmaskin en vinter som denna så att man kan dra upp egna skidspår. Efter att ha scannat av nätet för att se hur andra spårmaskiner är konstruerade så fick jag en uppfattning om hur jag skulle bygga den. Alternativet hade varit att köpa en färdig släde för ett antal tusen kronor, men hur kul hade det varit…

Jag utgick från pedahls utmärkta spårsläde. och hans utmärkta ritningar. Eftersom jag inte har några kunskaper om svetsning så tillverkade jag min i trä och plåt istället. Nackdelen med en sådan konstruktion är att det inte blir lika hållbart, men eftersom det är enkelt att tillverka nya ”reservdelar” så gör ju inte det något. Det som kommer att slitas mest är skidorna som gör själva spåren. Släden kommer inte att användas dagligen så min konstruktion kommer att uppfylla mina behov. Pajar något så kommer det att vara enkelt att fixa.

Jag hittade alla delar hemma på gården och bygget gick smärtfritt. Några kreativa lösningar fick funderas fram men alla fick bitar fick sin plats till slut. Efter några rundor med den färdiga släden så kan jag konstatera att det blir väldigt fina skidspår av min enkla spårdragare. Beroende på snöförhållanden så kan jag lasta på olika tyngder för att spåraren ska kunna pressa undan snön bättre. Efter att jag gjort klar släden så har jag dragit upp ett spår på ca 2km. Slutresultatet blev över alla förväntningar!

Här kommer några bilder på släden samt mina första spår:

Film från första provturen:

Bygget
1. Jag började med att bygga stommen i trä. En platta i botten och sedan sarger runtom denna.
2. Plåtskivan drogs sedan fast i trästommen.
3. Tillverkade skidorna/medarna enligt pedahls profilritning och drog fast dessa i plåten och stommen.
5. Byggde en enkel draganordning med ett armeringsjärn som böjdes till lämplig form. Ändarna fästes sedan i ett rör som dragits fast i trästommen.

Material
* Plåt
* Träbitar
* Armeringsjärn
* Rör
* Skruv

Kostnad: 0 kr (hade alla bitar tillgängliga), men borde inte bli särskilt dyr med prylar från byggvaruhus.
Tidsåtgång: 2-3 timmar

Framtida förbättringar
* Att installera något som bryter upp snön framför skidorna.
* Kanter på vardera sida i slädens riktning för att få släden att spåra mer rakt/stabilt.
* Montera plåt på skidorna/medarna för bättre hållbarhet.

Länkar
Build Your Own Cross-Country Ski Tracksetter for Grooming
Pedahl spårmaskin
Tims National Trail Grooming

Intressant läsning om spår och ledpreparering
Tracksetter
SKI TRAIL GROOMING GUIDE
GUIDELINES for SNOWMOBILE TRAIL GROOMER OPERATOR TRAINING
4.OPERATING GROOMING EQUIPMENT
2.GROOMING EQUIPMENT

Troubleshoooting device driver installation with setupapilog.txt

Today I tried to install the ”HP Universal Driver PCL6″ (32-bit) on a Windows XP machine with WMI and VB.NET. All I got was the errorcode 2 and a failed installation. What does that mean? Windows errorcodes is not my (anyones?) speciality…

After some googling I found this very good post that describes the problem and a possible solution.

The key to solving this puzzle and possibly other device installation problems is the file setupapi.log in the windows folder. After running my code again I got this in my setupapi.log file (in swedish):

[SetupAPI Log]
OS-version = 5.1.2600 Service Pack 3
Plattforms-ID = 2 (NT)
Service Pack = 3.0
Svit = 0x0100
Produkttyp = 1
Arkitektur = 2006157608
[2010/01/22 14:20:41 5392.4 Driver Install]
#-198 Bearbetad kommandorad: C:\WINNT\system32\wbem\wmiprvse.exe
#I060 Ange vald drivrutin.
#I060 Ange vald drivrutin.
[2010/01/22 14:20:41 5392.5]
#-198 Bearbetad kommandorad: C:\WINNT\system32\wbem\wmiprvse.exe
#-167 SPFILENOTIFY_NEEDMEDIA: Tagg = p6i2svww.cab, Beskrivning= PDL_LANG, Källsökväg = C:\CentralPrintArea\FKPrint\HP\Universal\32bit\HP Universal, Källfil = UNIDRV.HLP, Flaggor = 0x00000000.
#E169 SPFILENOTIFY_NEEDMEDIA: returnerade FILEOP_ABORT. Fel 2: Det går inte att hitta filen.
#W187 Installationen misslyckades. Försök att återställa originalfiler utförs.

It says that I got an errorcode 2 (missing file) and which file that is missing. In this case it is missing the file ”UNIDRV.HLP” that is not available in swedish. All I had to do is to extract this file from the cab-file ”p6i2svww.cab” to the root of the driverfolder. After doing this and running the program once more everything is working and the driver installs. After this I get the following output in setupapi.log.

[SetupAPI Log]
OS-version = 5.1.2600 Service Pack 3
Plattforms-ID = 2 (NT)
Service Pack = 3.0
Svit = 0x0100
Produkttyp = 1
Arkitektur = 2006157608
[2010/01/22 14:28:43 4784.4 Driver Install]
#-198 Bearbetad kommandorad: C:\WINNT\system32\wbem\wmiprvse.exe
#I060 Ange vald drivrutin.
#I060 Ange vald drivrutin.

That looks good I suppose! At least better then before. And the driver is installed ok!

You can read and download information about setupapilog.txt at the Microsoft website. If you read the whitepaper you could possibly solve many kinds of STRANGE device driver installation problems.

This is Microsofts description of setupapilog.txt

Windows XP and later versions log system operations more extensively than previous versions of Windows do. One of the most useful log files for debugging is the SetupAPI log file (setupapi.log). This plain-text file maintains the information that SetupAPI records about device installation, service-pack installation, and hotfix installation. Specifically, the file maintains a record of device and driver changes, as well as major system changes,

If you wnat more verbose logging to the setupapi.txt file you can edit the windows registry key ”HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\LogLevel”. If you raise this value to 255 you get a lot of logging which can be useful at times.

I hope this helps someone and that HP fixes the broken driver. It must be some sort of localization problem within this driver. Or maybe that I have the wrong driver…

There is always something new to learn in the Windows world! Happy troubleshooting!

How to create a printerqueu with .NET and WMI

This is an example of how you create a printerqueue with .NET and WMI (Windows Management Instrumentation).

A list of properties can be found at MSDN Win32_Printer

Other topics:
How to install printerdrivers with wmi and VB.NET
How to create TCP/IP printerports with .NET

Imports System.Management

Dim shared as Boolean = true

Try
 Dim mp As ManagementPath = New ManagementPath("Win32_Printer")
 Dim co As ConnectionOptions = New ConnectionOptions()
 co.EnablePrivileges = True
 co.Impersonation = ImpersonationLevel.Impersonate

 Dim ms As ManagementScope = New ManagementScope("\\" + Environment.MachineName + "\root\cimv2", co)

 Dim printerObject As ManagementObject = New ManagementClass(ms, mp, Nothing).CreateInstance()
 printerObject("PortName") = "IP_192.168.0.2"
 printerObject("DriverName") = "DriverName"
 printerObject("DeviceID") = "queuename"
 printerObject("Location") = "Placement of printer"
 printerObject("Comment") = "Some comments"

 If (shared) Then
  printerObject("Shared") = True
  printerObject("ShareName") = "Sharename"
  'printerObject("Published") = False ' Publish printer
 End If

 Dim options As PutOptions = New PutOptions()
 options.Type = PutType.UpdateOrCreate
 printerObject.Put(options)

Catch ex As Exception
 ' Do something
End Try

Nagios check_nt over ssh-tunnel

I am a big fan of Nagios for host and service monitoring and this is my first post on the subject. My task was to check services on a Windows Server with Nagios and NSClient++. But the firewall only allowed me to use ssh and thats why I could not connect to port 12489 (that NSClient listens to) from my Nagios server. The only way to solve the problem was to use a SSH-tunnel that I can open and close whenever I needed to.

Workflow for my solution
1. Nagios initiates that a service should be checked.
2. Nagios executes the check_nt_by_ssh_tunnel check-command with additional parameters
3. The script creates a ssh-tunnel
4. The script checks the Windows server with the Nagios builtin command check_nt
5. The script returns the check_nt output
6. The script closes the ssh-tunnel
7. Nagios does its processing.

Prerequisites
* A fully working Nagios installation
* NSClient installed and working on the Windows Server that should be monitored
* SSH autologin is configured between the two machines
* Read my other article for details about the SSH-tunnel used in this solution.

First you have to create the check-script on the Nagios server (in the Nagios libexec-folder). See below:

check_nt_by_ssh_tunnel.sh

#!/bin/bash

# $1 = HOSTNAME, 83.121.233.2
# $2 = LOCAL PORT, 14880
# $3 = USERNAME, ex: someusername
# $4 = CHECK PARAMETERS, ex: -w 80 -c 90 -v MEMUSE

if [ -z "$1" ]
then
        echo "Missing HOSTNAME"
        exit
fi

if [ -z "$2" ]
then
        echo "Missing LOCAL PORT"
        exit
fi

if [ -z "$3" ]
then
        echo "Missing USERNAME"
        exit
fi

# Open ssh-tunnel and wait for it to open
ssh -f -N -L $2:localhost:12489 $3@$1 &
sleep 30

# Run check_nt command
CHECK="/usr/local/nagios/libexec/check_nt -H localhost -p $2 $4"
#echo $CHECK
eval $CHECK

# Close ssh-tunnel
sleep 5
CMD="ps -eo pid,args | grep 'ssh -f -N -L $2:localhost' | grep -v  'grep' | cut -c1-6"
#echo $CMD
PID=`eval $CMD`
#echo $PID
kill -9 $PID

Make it executable:
chmod 755 check_nt_by_ssh_tunnel.sh

Then verify that i works by running the command:
./check_nt_by_ssh_tunnel.sh 83.121.233.2 14880 someusername ”-w 80 -c 90 -v MEMUSE”

You should then either see a valid Nagios plugin-output or get an error-message. Make sure that is works! You may have to modify the script depending on your *nix OS.

Next modify Nagios checkcommands.cfg or similiar and add the following. This makes the command available for use in Nagios.

# USAGE: check_nt_by_ssh_tunnel!11101!username!"-l 5,80,90 -v CPULOAD"
define command{
	command_name		check_nt_by_ssh_tunnel
	command_line		PATH_TO_COMMAND/check_nt_by_ssh_tunnel.sh $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$
}

Next add a service definition that uses the check-command.

define service{
	use				       generic-service
        host_name                        MY_HOSTNAME
        service_description             Memory usage
        check_command                 check_nt_by_ssh_tunnel!11100!username!"-w 80 -c 90 -v MEMUSE"
}

The last step you need to do is to restart Nagios and check if it works.

* I recommend you to change the portnumber for each service-definition to avoid collisions. Make them unique to the service-check.

Bash script that open and close an ssh-tunnel automagically

My problem was that I needed to connect to a port on a server that only was accessible by ssh. This connection should be made in a bash-script that starts and ends within a limited timeframe. That’s why I needed to solve the problem with a SSH-tunnel. George Notaras has made an article about auto-closing ssh tunnels that describes the problem and a solution that should work for most people. However, I did not need a auto-closing ssh tunnel because I want to close the tunnel whenever I want to.

My solution is a little bit more brute because it kills the tunnel. But hey, it works! Check out the simple solution below.

Prerequisites
For this to work you need to have ssh auto login between the two servers.

I have used this solution successfully with the Nagios monitoring system. Read Nagios check_nt over ssh-tunnel.

#!/bin/bash

# Open tunnel and wait for it to open
# 12489 = remote portnumber
# 3456  = local portnumber
# increase sleep-time if slow to connect
ssh -f -N -L 3456:localhost:12489 username@somehost &
sleep 30

# Run some command that uses the opened tunnel
# telnet localhost 3456

# Close the tunnel by killing it
sleep 5
CMD="ps -eo pid,args | grep 'ssh -f -N -L 3456:localhost' | grep -v  'grep' | cut -c1-6"
#echo $CMD
PID=`eval $CMD`
#echo $PID
kill -9 $PID

You may have to change the parameters to the ps-command for this to work on your nix-machine.

Install printerports with WMI and VB.NET

This is an example of how you install TCP/IP printerports with .NET and WMI (Windows Management Instrumentation).

A list of properties can be found at MSDN Win32_TCPIPPrinterPort

Other topics:
How to install printerdrivers with wmi and VB.NET
How to create a printerqueu with .NET and WMI

Imports System.Management

Try
  Dim mp As ManagementPath = New ManagementPath("Win32_TCPIPPrinterPort")
  Dim co As ConnectionOptions = New ConnectionOptions()
  co.EnablePrivileges = True

  Dim ms As ManagementScope = New ManagementScope("\\" + Environment.MachineName + "\root\cimv2", co)

  Dim port As ManagementObject = New ManagementClass(ms, mp, Nothing).CreateInstance()
  port.SetPropertyValue("Name", "portname")
  port.SetPropertyValue("Protocol", 1)
  port.SetPropertyValue("HostAddress", "10.15.12.12")
  port.SetPropertyValue("PortNumber", "9100")

  Dim po As PutOptions = New PutOptions()
  po.UseAmendedQualifiers = True
  po.Type = PutType.UpdateOrCreate
  port.Put(po)
Catch ex As Exception
  ' do something
End Try

Marvel 6162 SATA driver for Windows 7

There isn’t any driver for the Marvel 6162 (88SE6162) SATA controller in Windows 7 (32-bit). For my motherboard (Asus M2V) I needed this driver and I could not find them on the Asus support website. I guess Asus havn’t made these available yet. Lazy bastards! After some modifications to the Vista-drivers I could use them instead.

marvel-6162-sata-driver

If you download and try to install the Vista-drivers you get a message like ”Does not support this Operating System : WNT_6.1P_MCE”. To be able to run the installer you need to edit the AsusSetup.ini file with notepad. The only thing you need to do is add a line corresponding to your Operatingsystem (WNT_6.1P_MCE) in the [OS_Language_Tag] section of the file.

I have prepared a file for Windows 7 32-bit that you can use:
Download Marvell_SATA_V10215B2 driver.

You only have to extract the files and run the AsusSetup file in the driver/x32 folder. If you run Windows 7 64-bit you can use the same files and make the same changes. If someone does this then please contribute to this post.

The driver installer then works great and the drivers are working. My SATA-drive has appeared and I am happy again.

Problem installing Windows 7 on Asus motherboards

For the last 5 hours I tried to install Windows 7 (x86, 32bit) on my home computer that has an Asus M2V motherboard. I tried everything in the book and couldn’t install it. I removed and switched hardware, reburned the DVD, updated the BIOS and did everything that I could possibly think of. The installation process always hung when the installer says ”expanding windows files”. No error messages or nothing and the installation percentage counter stops at a random number. That really pissed me of!

Finally I found an answer to this really weird behaviour. It seems that this is common problem on Asus motherboards and Windows 7.

In BIOS you have to make these changes to make it work:
* Enable the floppy drive (I had it disabled because I dont have a floppy drive).
* Disable the ”Cool and quite” feature.

After I made these changes the installation worked!

I hope this helps other people stuck with the really annoying ”Windows 7″ installer.

Install printerdrivers with WMI and VB.NET

This is an example of how you install printerdrivers with .NET and WMI (Windows Management Instrumentation). Most examples on the Internet shows how this can be done with vbscript, printui.dll and such…

A list of properties can be found at MSDN Win32_PrinterDriver

Other topics:
How to install printerports with WMI and VB.NET
How to create a printerqueu with .NET and WMI

Imports System.Management

Dim infPath  as String = "c:\driver\printerdriver.inf"
Dim mp As ManagementPath = New ManagementPath("Win32_PrinterDriver")

Dim co As ConnectionOptions = New ConnectionOptions()
co.EnablePrivileges = True

Dim ms As ManagementScope = New ManagementScope("\\" + Environment.MachineName + "\root\cimv2", co)

Dim mcPrinterDriver As New ManagementClass(ms, mp, Nothing)
mcPrinterDriver.SetPropertyValue("Name", "drivername")
mcPrinterDriver.SetPropertyValue("SupportedPlatform", "Windows NT x86") ' x86-architecture
'mcPrinterDriver.SetPropertyValue("SupportedPlatform", "Windows x64") ' x64-architecture
mcPrinterDriver.SetPropertyValue("Version", 3)
mcPrinterDriver.SetPropertyValue("FilePath", System.IO.Path.GetDirectoryName(infPath))
mcPrinterDriver.SetPropertyValue("InfName", infPath)

Dim inParams As System.Management.ManagementBaseObject = Nothing
inParams = mcPrinterDriver.GetMethodParameters("AddPrinterDriver")
inParams("DriverInfo") = CType(mcPrinterDriver, System.Management.ManagementBaseObject)
Dim outParams As System.Management.ManagementBaseObject = mcPrinterDriver.InvokeMethod("AddPrinterDriver", inParams, Nothing)

Dim uiReturnValue As UInteger = System.Convert.ToUInt32(outParams.Properties("ReturnValue").Value)

I have tested this in Windows XP, Windows 7 and Windows 2008R2. Make sure your account has privileges to install drivers.

On Windows XP the drivers are installed physically to:
C:\WINNT\system32\spool\drivers

And in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments