<?php
   /*
   |  ========================================================================  |
   |
   |  Yazar (Author)     : Yusuf Tuğrul Kocaman
   |  Yazar URL          : http://www.kulturlupenguen.com
   |  Sürüm (Version)    : 1.0 
   |  Tarih (Date)       : 13 Nisan 2013 (April 13, 2013)
   |  Amaç (Purpose)     : HTML veya text/plain şeklinde verileri SMTP
   |  üzerinden gönderir. SMTP doğrulaması yaptırarak sanki bir e-posta
   |  arayüzünden göndermiş görüntüsü verir.
   |  Gereksinimler (Requires): Min PHP Ver.: 5.0.0 ve multiByte kütüphanesi 
   |  MIT ve GPL lisansı ile korunmaktadır.Bunun dışında asıl kaynak olarak beni ve blogumu
   |  gösterdikten sonra istediğiniz şekilde kullanabilirsiniz.
   |  ========================================================================= |
   */

define('script_name','phpPosta'); define('phpPosta_ver','1.0.0'); define('phpPosta_author','Yusuf Tuğrul Kocaman');
   
class phpPosta{

    /**
      * Debug yapmak için gerekli olan bilgiler.
      * @var bool
      */
	public $debug = false;

    /**
	* SMTP sunucusunun bağlantı noktasıdır. Bazı 
	* sunucularda farklılık gösterebilir.
	* @var int
	*/
	public $smtpPort = 587;
	
    /**
      * SMTP sunucuyla aramızda kurulacak olan bağlantı
      * için yetkilendirme yapmamız gerekir. Bu yetkilendirme
      * için bir kullanıcı adı lazım. Bu kullanıcı adı da e-posta
      * adresimiz oluyor.
      * @var string
      */
	public $smtpUser;
   
    /**
      * SMTP sunucusuna kullanıcı adıyla bağlandıktan 
      * sonra o kullanıcı adının biz olduğunu belirtmemiz
      * gerekir. İşte o belirtmeyi şifreyle yaparız.
      * @var string
      */
      public $smtpPassword;
    
    /**
      * SMTP bağlantısı için SMTP sunucusu
      * @var string
      */
    	private $smtpServer;
    /**  
      * E-posta yollandıktan sonra görünecek isim
      * E-posta adresinin yanında gözükür.
      * Mesela "Yusuf Tuğrul Kocaman <yusuftugrul@kulturlupenguen.com>"
      * @var string
      */
      public $mailKimden;
    
    /**
      * Posta gönderimi sırasında üst bilgi ayarlarken
      * kullanılacak olan bu değişken, phpPosta::kime()
      * fonksiyonuyla beraber belirlenir.
      * @var string
      */
      private $mailKime;
      
    /**
      * SMTP sunucuya ulaşım sağladıktan sonra
      * birtakım haberleşme kodlarını kullanırız.
      * Bu kodlardan sonra yeni satır işareti kullanmamız
      * gerekir. Bu yeni satır işareti olmazsa kodlar çalışmaz.
      * @var string
      * Not: Lütfen düzenlemeyin!
      */
      private $satirBasi = "\r\n"; // \r aslında \n ile aynı görevi görür. Ama MAC makinelerde.

    /**
      * SMTP sunucuya olan bağlantımızda
      * her şey istediğimiz gibi gitmeyebilir.
      * Bu hataları bir diziye aktarmak bizim için
	* en kolay yol olacaktır.
	* @var array
	*/
	  public $errorLog = array();
	
    /**
      * SMTP sunucusuyla yaptığımız bağlantıyı
      * sağlayacak olan değişkendir. Her seferinde
      * yeni bir bağlantı açmak yerine var olan bağlantıyı
      * kullanmak daha basit olacaktır.
      * @var fsockopen
      */
	  private $smtpBaglantisi;
	
    /**
      * SMTP sunucunun "HELO" komutuna verdiği yanıtı içerir.
      * @var string
      */
      private $merhabaYanit;
    
	/**
      * Gönderilecek postadaki başlık şöyleyse "merhaba dünya!"
	  * "Merhaba Dünya!" şekline dönüşütürür.
      * @var bool
	  */
	  public $baslikOptimizasyon;
	
	/**
	  * Gönderilecek postanın HTML veya Plain (text) formatında
	  * olup olmayacağını bildiren değişkendir.
	  * @var bool
	  */
	  private $plain = true;
	/**
      * Sınıfı başlat
      * @return void
      */

	  
	  public function __construct()
	  {
		$this->smtpBaglantisi = null;
		$this->merhabaYanit = null;
		$this->errorLog = array();
	  }
	
    /**
      * SMTP sunucudan alınan son cevabı gösterir.
      * 512 bayt veri alır.
      * @return str
      */      
      private function sonMesaj()
      {
			return fread($this->smtpBaglantisi, 250);
      }
	
	/**
	  * Gönderilecek postanın türünü ayarlar.
	  * Plain (text) veya HTML.
	  * @return void
	  */
	  public function HTML($html = false)
	  {
			if( $html == false )
			{
				$this->plain = true;
			} else {
				$this->plain = false;
			}
			
	  }
	/**
	  * Sunucuya bağlanıldı mı diye kontrol eder.
	  * Kontrol başarılıysa diğer işleme geçer.
	  * @return bool
	  */
	  private function __isConnected()
	  {
			if( !empty($this->smtpBaglantisi ) ) 
			{
				return true;
			} else {
				return false;
			}
				
	  }
    /**
      * SMTP sunucuya bağlanma işlemini gerçekleştir.
      * @param smtpServer string
      * @param timeOut int
      * @return bool
      */	
      public function Baglan($smtpServer, $timeOut = 5)
      {
      	if( empty($smtpServer) )
      	{
      		$this->errorLog[] = array(
      		'hata' => 'phpPosta::baglan() için parametre hatası',
      		'hata_aciklama' => '$smtpServer değişkeni boş bırakılmamalı!'
      		);
      	}
      	
      	$this->smtpServer = $smtpServer;
      	$this->smtpBaglantisi = fsockopen(
      					$this->smtpServer, // Sunucu adresi
      					$this->smtpPort, // Bağlantı noktası
      					$hataKod, // Hata kodu
      					$hataAciklama, // Hata açıklaması
      					$timeOut // Belirlenen saniyede de bağlanamıyorsa boşver gitsin.
      					);
      	
      	if( !$this->smtpBaglantisi )
      	{
      		$this->errorLog[] = array(
      		'hata' => 'phpPosta::baglan() için bağlantı sorunu',
      		'hata_aciklama' => "SMTP sunucuya bağlanırken, sunucu şu kodları döndürdü:{$hataAciklama} ve kodu {$hataKod}"
      		);
      	}else{
  		// Bağlantı sağlandı.    
  		return true;
  		
      	}      
      }
	
    /**
      * SMTP sunucuya kendimizi tanıtma vakti geldi.
      * Bu tanıtma olayını yapmamız için fputs kullanacağız.
      * İlk önce merhaba dememiz gerekiyor.
      * @return bool
      */
      public function Merhaba()
      {
	  	if( !$this->__isConnected( ) )
		{
				$this->errorLog[] = array(
				'hata' => 'SMTP sunucuyla bağlantı sağlanamadı.',
				'hata_aciklama' => 'SMTP sunucusuna bağlantı yapılmamış veya sunucu bağlantıyı kapatmış olabilir.'
				);
				exit(0); // Programı bitir.
		}
		
      	fputs($this->smtpBaglantisi, "EHLO " . $this->satirBasi); 
      	// Merhaba
      	      $son = $this->sonMesaj();
      		$erKod = mb_substr($this->sonMesaj(), 0, 3, 'UTF-8');
      		if( $erKod != 250) // Merhaba iletisine 220 ile cevap verir.
      		{
      			$this->errorLog[] = array(
      			'hata' => 'phpPosta::Merhaba() için SMTP sunucu sorunu',
      			'hata_aciklama' => $this->smtpServer .' "MERHABA" iletisini kabul etmiyor!'
      			);
      		}
      		
      		$this->merhabaYanit = $son;

            return true; // Her şey tamam. İşleme başlayabiliriz.
      }
      
    /**
      * SMTP sunucuda oturum açmalıyız.
      * Bu oturumu açarken şifre ve kullanıcı adını
      * base64 ile şifreleyip göndermemiz gerekiyor.
      * @return bool
      */
      public function Yetkilendirme()
      {
	  	if( !$this->__isConnected( ) )
		{
				$this->errorLog[] = array(
				'hata' => 'SMTP sunucuyla bağlantı sağlanamadı.',
				'hata_aciklama' => 'SMTP sunucusuna bağlantı yapılmamış veya sunucu bağlantıyı kapatmış olabilir.'
				);
				exit(0); // Programı bitir.
		}
		
      	// İşlemi başlat
      	fputs($this->smtpBaglantisi, "AUTH LOGIN" . $this->satirBasi);
      	$this->sonMesaj();
      	
      	// Kullanıcı adını gönder.
      	fputs($this->smtpBaglantisi, base64_encode($this->smtpUser) . $this->satirBasi);
      	
      	$err = mb_convert_encoding($this->sonMesaj(),'UTF-8');
      	$erKod = mb_substr($err, 0, 3);
      	
      	if( $erKod != 334 ) // Kullanıcı adının alındığına dair gönderilen hata kodudur.
      	{
      		$this->errorLog[] = array(
      		'hata' => 'phpPosta::Yetkilendirme() için yetkilendirme hatası!',
      		'hata_aciklama' => 'SMTP sunucusu gönderdiğiniz kullanıcı adını kabul etmedi: '.$err
      		);
      	}
      	
      	// Şifreyi gönder
      	fputs($this->smtpBaglantisi, base64_encode($this->smtpPassword) . $this->satirBasi);
      	
      	$err = mb_convert_encoding($this->sonMesaj(), 'UTF-8');
      	$erKod = mb_substr($err, 0, 3, 'UTF-8');
      	
      	if( $erKod != 235 ) // Şifre doğrulandığında gönderilen başarı kodudur.
      	{
      		$this->errorLog[] = array(
      		'hata' => 'phpPosta::Yetkilendirme() için yetkilendirme hatası!',
      		'hata_aciklama' => 'SMTP sunucu gönderdiğiniz bilgilere göre bir kullanıcı olmadığını belirtiyor:'. $err
      		);
      		
      		return false; // Şifre yanlış. Geri dön!
      	}
      	
      	return true; // İçeri girdik! Şu an sunucudayız!
      }
      
    /**
      * SMTP sunucuda yetkilendirmeden sonra göndereceğimiz postanın
      * kimden geldiğini belirtmemiz gerekiyor. Kimse anonim postaları
      * sevmez.
      * @return bool
      */  
      public function Kimden()
      {
	  	if( !$this->__isConnected( ) )
		{
				$this->errorLog[] = array(
				'hata' => 'SMTP sunucuyla bağlantı sağlanamadı.',
				'hata_aciklama' => 'SMTP sunucusuna bağlantı yapılmamış veya sunucu bağlantıyı kapatmış olabilir.'
				);
				exit(0); // Programı bitir.
		}
      	// İşlemi başlat
      	fputs($this->smtpBaglantisi, "MAIL FROM: <{$this->smtpUser}>" . $this->satirBasi);

		$err = mb_convert_encoding($this->sonMesaj(), 'UTF-8');
		$erKod = mb_substr($err, 0, 3, 'UTF-8');
		
		if( $erKod != 250 )
		{
			$this->errorLog[] = array(
			'hata' => 'phpPosta::Kimden() için sunucu hatası!',
			'hata_aciklama' => 'SMTP sunucu "MAIL FROM" komutunu kabul etmiyor: '.$err
			);
			return false;
		}      
      	
      	return true;
      }
    /**
      * Her şey hazır. Şimdi tek yapmamız gereken e-postayı yollamak.
      * Bunun için DATA komutunu kullanıyoruz.
      * Mesaj gövdesini ve header bilgilerini hazırlayıp postalamak kalıyor.
      * @return bool
    	*/
    	public function Mail($mesaj, $konu, $headers = null)
    	{
			if( !$this->__isConnected() )
			{
				$this->errorLog[] = array(
				'hata' => 'SMTP sunucuyla bağlantı sağlanamadı.',
				'hata_aciklama' => 'SMTP sunucusuna bağlantı yapılmamış veya sunucu bağlantıyı kapatmış olabilir.'
				);
				exit(0); // Programı bitir.
			}
		
    		// İşlemi başlat
    		fputs($this->smtpBaglantisi, "DATA" . $this->satirBasi);
    		$err = mb_convert_encoding($this->sonMesaj(), 'UTF-8');
    		$erKod = mb_substr($err, 0, 3, 'UTF-8');
    		
    		if( $erKod != 354 )
    		{
    			return false;
    		}
    	    /**
    		* Gönderilen bilgileri UTF-8'e çevirmemiz gerekiyor.
    		* Mesaj, alıcı, header bilgileri.
    		* multiByte kullanır.
    		*/
    		mb_convert_encoding( $mesaj, 'UTF-8');
    		mb_convert_encoding( $konu, 'UTF-8');
			
			// Mail optimizasyonu etkinleştirildiyse bazı işlemler uygula
			if( $this->baslikOptimizasyon )
			{
							mb_convert_case( $konu, MB_CASE_TITLE, 'UTF-8'); // Konuyu başlık formatına çevir
							
    		}
			
			// İçerik türü
			if( $this->plain == true )
			{
			
				$contentType = 'text/plain;charset=UTF-8';
			
			} else {
			
				$contentType = 'text/html;charset=UTF-8';
			
			}

			
			if( $headers != null )
    		{
    			mb_convert_encoding( $headers, 'UTF-8' );
    		}
    		
	     /**
		 * Postayı gönderirken, SMTP'ye bağlanma dışında yapacağımz bir
		 * önemli iş daha var. O da üst bilgileri ayarlamak. Üst bilgi-
		 * lerden kısaca bahsetmek gerekirse, aynı HTTP gibi kendini
		 * istemciye tanıtan bilgilerdir. Bazı sunucularda spam kontro-
		 * lünden geçerken bu bilgilere de bakılır. Bu bilgilerde
		 */
    		if( $headers == null)
    		{
	    		$headers = "To: <". $this->mailKime .">" . $this->satirBasi;
	    		$headers .= "From: ".$this->mailKimden." <". $this->smtpUser .">" . $this->satirBasi;
	    		$headers .= "Subject: $konu" . $this->satirBasi;
	    		$headers .= "Reply-To: ". $this->mailKimden ." <".$this->smtpUser.">". $this->satirBasi;
	    		$headers .= "X-Mailer: ". script_name ." ". phpPosta_ver . $this->satirBasi;
	    		// E-postayı gönderen yazılım
	    		$headers .= "Importance: Normal" . $this->satirBasi;
	    		$headers .= "Date: ".date('r') . $this->satirBasi;
	    		$headers .= "MIME-Version: 1.0". $this->satirBasi;
	    		$headers .= "X-Priority: 3" . $this->satirBasi;
	    		$headers .= "Content-Type: $contentType" . $this->satirBasi;
	    		// İçerik türü ve karakter kodlaması
	    		$headers .= "Message-ID: <".md5( date('r') ).">" . $this->satirBasi;
	    		// Benzersiz mesaj kimliği
	    		$headers .= "Sender: ". $this->smtpUser . $this->satirBasi; 
	    		// Postayı gönderen e-posta adresi
    		}

    		// YOLLA!!!!
    		fputs($this->smtpBaglantisi,
    		$headers . str_repeat($this->satirBasi, 2) // Üst bilgiler
    		.$mesaj // Mesaj
    		.str_repeat($this->satirBasi, 2) . "." . str_repeat($this->satirBasi, 2) ); // Mesaj gövdesi.
 
    		$err = mb_convert_encoding($this->sonMesaj(), 'UTF-8');
    		$erKod = mb_substr($err, 0, 3, 'UTF-8');
    		
    		if( $erKod == 250 )
    		{
    			return true; // Tebrikler, posta gönderildi!
    		}else{
    			$this->errorLog[] = array(
    			'hata' => 'phpPosta::Mail() için posta gönderilemedi hatası!',
    			'hata_aciklama' => 'Mail gönderiminde bir hata oluştu: '.$err
    			);
    			return false; // Bir yerde hata var.
    		}
    		
    	}
    	
    /**
      * SMTP sunucuda yetkilendikten sonra e-postanın
      * hangi e-posta adresine gönderileceği belirlemek gerekiyor.
      * Bunun için bu fonksiyon birebir. RCPT TO: <[e-posta]>
      * @return bool
      */  
      public function Kime($eMail)
      {
		if( !$this->__isConnected() )
			{
				$this->errorLog[] = array(
				'hata' => 'SMTP sunucuyla bağlantı sağlanamadı.',
				'hata_aciklama' => 'SMTP sunucusuna bağlantı yapılmamış veya sunucu bağlantıyı kapatmış olabilir.'
				);
				exit(0); // Programı bitir.
		}
	  
      	if( !filter_var($eMail, FILTER_VALIDATE_EMAIL) ){
      		die('Girdiğiniz e-posta adresi geçersiz.');
      	}
      	// İşlemi başlat!
      	fputs($this->smtpBaglantisi,"RCPT TO: <{$eMail}>" . $this->satirBasi);
		$this->mailKime = $eMail;
		
      	$durum = mb_stripos($this->sonMesaj(),"Accepted",0, "UTF-8"); 
		/** Dönen kodun içerisine kabul
      	  * edildiğine dair işaret var mı diye ara.
		  */
      	if( $durum == false) // Farklı programlarda farklı kodlarla kabul edebilir.
      	{
      		$this->errorLog[] = array(
      		'hata' => 'phpPosta::Kime() için SMTP sunucu hatası!',
      		'hata_aciklama' => 'SMTP sunucu "RCPT TO" kodunu kabul etmiyor.'
      		);
      		return false; // Bu iş burada bitmiştir!
      	}    	
      	return true; // Aha tamam bu da!
      }

	/**
	  * SMTP bağlantısını kapatır.
	  * @return void
	  */
	  public function Kapat()
	  {
	  
			if( $this->__isConnected() )
			{
				fputs($this->smtpBaglantisi, 'QUIT' . $this->satirBasi); // SMTP sunucuyla bağlantıyı kes.
			} else {
				$this->errorLog[] = array(
				'hata' => 'Not: Bağlantı yok. Bu yüzden hiçbir şey kapatılmadı.',
				'hata_aciklama' => 'Zaten SMTP sunucuyla bağlantı yapılmamış.'
				);
			}
			
	  }
	/**
	  * Bitiş fonksiyonudur. Eğer debug değişkeni
	  * TRUE değer aldıysa hataları yazdırır.
	  */
      public function __destruct()
      {
    		if( $this->debug )
    		{
    			foreach( $this->errorLog as $error )
    			{
    				echo "Hata: " . $error['hata'] . "<br>";
    				echo "Açıklama: " . $error['hata_aciklama'] . "<br>";
    				echo "<br />";
    			}
				
    		}
      }
}
// :)
?>