diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,11 @@
+0.2.0
+=====
+
+  * Require [LDAP](https://hackage.haskell.org/package/LDAP) > 0.6.0 for `ldapExternalSaslBind`.
+  * Support simple bind. Added options `-x`, `-D`, `-w`, `-y` similar to `ldapmodify`.
+  * `changetype: delete` works if entry to be deleted does not exist.
+
+
 0.1.0
 =====
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -33,9 +33,16 @@
     Options:
       -H <ldapuri>       LDAP URL to connect to [default: ldapi:///]
 
+      -x                 Use simple bind instead of default SASL External
+      -D <binddn>        Use <binddn> for the distinguished name or authorization identity
+      -w <passwd>        Use <passwd> as the password for simple bind
+      -y <passwdfile>    Read password from <passwdfile>, only the first line is read
+
       -h, --help         Show this message
 
+    If option -w is given, -y is ignored.
 
+
 LDIF example
 ============
 
@@ -73,5 +80,10 @@
 changetype: modify
 replace: description
 description: foo
+
+# This will be deleted if exists:
+dn: cn=reader,dc=nodomain
+changetype: delete
+
 ```
 
diff --git a/ldapply.cabal b/ldapply.cabal
--- a/ldapply.cabal
+++ b/ldapply.cabal
@@ -1,5 +1,5 @@
 name: ldapply
-version: 0.1.0
+version: 0.2.0
 synopsis: LDIF idempotent apply tool
 license: MIT
 license-file: LICENSE
@@ -11,6 +11,10 @@
 cabal-version: >=1.20
 extra-source-files: README.md ChangeLog.md
 
+source-repository head
+  type: git
+  location: https://github.com/ip1981/ldapply.git
+
 executable ldapply
   hs-source-dirs: src
   main-is: Main.hs
@@ -22,7 +26,7 @@
     , bytestring
     , docopt
     , interpolatedstring-perl6
-    , LDAP >= 0.7.0
+    , LDAP > 0.6.10
     , ldif
     , unordered-containers
 
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -6,15 +6,16 @@
 import Data.ByteString.Char8 (unpack)
 import Data.Char (toLower)
 import Data.HashMap.Strict (fromListWith, toList)
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Data.Version (showVersion)
-import LDAP.Init (ldapSimpleExternalSaslBind, ldapInitialize)
+import LDAP.Init (ldapSimpleBind, ldapExternalSaslBind, ldapInitialize)
 import LDAP.Modify (LDAPMod(..), LDAPModOp(..), ldapAdd, ldapDelete, ldapModify, list2ldm)
 import LDAP.Search (LDAPScope(LdapScopeBase), SearchAttributes(LDAPAllUserAttrs), LDAPEntry(..), ldapSearch)
 import LDAP.Types (LDAP)
 import Paths_ldapply (version) -- from cabal
 import System.Environment (getArgs)
 import System.Exit (die)
+import System.IO (IOMode(ReadMode), hGetLine, hIsEOF, withFile)
 import Text.InterpolatedString.Perl6 (qc)
 import Text.LDIF.Parser (defaulLDIFConf, parseLDIFFile)
 import Text.LDIF.Printer (dn2str)
@@ -24,7 +25,6 @@
 {--
  TODO:
     1. Streaming from stdin (good for large amount of LDIF data)
-    2. Simple bind with DN and password
 --}
 
 usage :: String
@@ -38,7 +38,14 @@
 Options:
   -H <ldapuri>       LDAP URL to connect to [default: ldapi:///]
 
+  -x                 Use simple bind instead of default SASL External
+  -D <binddn>        Use <binddn> for the distinguished name or authorization identity
+  -w <passwd>        Use <passwd> as the password for simple bind
+  -y <passwdfile>    Read password from <passwdfile>, only the first line is read
+
   -h, --help         Show this message
+
+If option -w is given, -y is ignored.
 |]
 
 
@@ -52,11 +59,26 @@
     let
       ldifs = O.getAllArgs args $ O.argument "LDIF"
       ldapUrl = fromJust $ O.getArg args $ O.shortOption 'H'
+      simple = O.isPresent args $ O.shortOption 'x'
+      binddn = fromMaybe "" $ O.getArg args $ O.shortOption 'D'
+      passwd = O.getArg args $ O.shortOption 'w'
+      passwdfile = O.getArg args $ O.shortOption 'y'
     ldap <- ldapInitialize ldapUrl
-    ldapSimpleExternalSaslBind ldap
+    if simple then simpleBind ldap binddn passwd passwdfile
+              else ldapExternalSaslBind ldap binddn
     mapM_ (processLDIF ldap) ldifs
 
 
+simpleBind :: LDAP -> String -> Maybe String -> Maybe FilePath -> IO ()
+simpleBind ldap bdn (Just pwd)  _    = ldapSimpleBind ldap bdn pwd
+simpleBind ldap bdn Nothing Nothing  = ldapSimpleBind ldap bdn ""
+simpleBind ldap bdn Nothing (Just f) = do
+  pwd <- withFile f ReadMode $ \h -> do
+    empty <- hIsEOF h
+    if empty then return "" else hGetLine h
+  ldapSimpleBind ldap bdn pwd
+
+
 processLDIF :: LDAP -> FilePath -> IO ()
 processLDIF ldap f = do
   p <- parseLDIFFile defaulLDIFConf f
@@ -81,6 +103,8 @@
 
 
 update :: LDAP -> Maybe LDAPEntry -> LDIFRecord -> IO ()
+update _ Nothing (ChangeRecord _ ChangeDelete) = return ()
+
 update _ Nothing rec@(ChangeRecord _ _) =
   die $ "cannot update non-existing entry " ++ show (dn rec)
 
